@creature-ai/sdk 0.1.8 → 0.1.10

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.
@@ -47,13 +47,9 @@ interface AdapterOptions {
47
47
  realtimeAdapter?: RealtimeAdapter;
48
48
  }
49
49
  /**
50
- * Options for vercelMcp adapter.
50
+ * Options for Vercel serverless handler.
51
51
  */
52
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
53
  }
58
54
  /**
59
55
  * Options for awsLambda adapter.
@@ -508,13 +504,16 @@ declare class App {
508
504
  */
509
505
  getResourceDefinitions(): Map<string, ResourceDefinition>;
510
506
  /**
511
- * Create a Vercel MCP adapter configuration.
512
- * For use with Vercel's `mcp-handler` package.
507
+ * Create a Vercel serverless function handler.
508
+ * Works with plain Vercel Serverless Functions - no Next.js or mcp-handler needed.
513
509
  *
514
- * Note: This returns a configuration callback. The implementation
515
- * is inline to avoid circular dependencies.
510
+ * Usage in api/mcp.ts:
511
+ * ```ts
512
+ * import { app } from "../src/app";
513
+ * export default app.toVercelFunctionHandler();
514
+ * ```
516
515
  */
517
- toVercelMcp(options?: VercelMcpOptions): (server: any, _context: any) => void;
516
+ toVercelFunctionHandler(options?: VercelMcpOptions): (reqOrRequest: any, res?: any) => Promise<any>;
518
517
  /**
519
518
  * Create an AWS Lambda handler.
520
519
  *
@@ -555,10 +554,19 @@ declare class App {
555
554
  */
556
555
  private formatServerlessResult;
557
556
  /**
558
- * Create a Vercel MCP configuration callback.
559
- * Returns a function compatible with Vercel's mcp-handler createMcpHandler.
557
+ * Create a Vercel serverless function handler.
558
+ * Handles MCP JSON-RPC protocol directly - no mcp-handler or Next.js needed.
559
+ */
560
+ private createVercelHandler;
561
+ /**
562
+ * Handle an MCP JSON-RPC request.
563
+ * Shared logic for all serverless handlers.
564
+ */
565
+ private handleMcpRequest;
566
+ /**
567
+ * Convert Zod schema to JSON Schema for tool definitions.
560
568
  */
561
- private createServerlessConfig;
569
+ private zodToJsonSchema;
562
570
  /**
563
571
  * Create an AWS Lambda handler function.
564
572
  */
@@ -12180,7 +12180,7 @@ var toRequestError = (e) => {
12180
12180
  return new RequestError(e.message, { cause: e });
12181
12181
  };
12182
12182
  var GlobalRequest = global.Request;
12183
- var Request = class extends GlobalRequest {
12183
+ var Request2 = class extends GlobalRequest {
12184
12184
  constructor(input, options) {
12185
12185
  if (typeof input === "object" && getRequestCache in input) {
12186
12186
  input = input[getRequestCache]();
@@ -12213,7 +12213,7 @@ var newRequestFromIncoming = (method, url, headers, incoming, abortController) =
12213
12213
  };
12214
12214
  if (method === "TRACE") {
12215
12215
  init.method = "GET";
12216
- const req = new Request(url, init);
12216
+ const req = new Request2(url, init);
12217
12217
  Object.defineProperty(req, "method", {
12218
12218
  get() {
12219
12219
  return "TRACE";
@@ -12250,7 +12250,7 @@ var newRequestFromIncoming = (method, url, headers, incoming, abortController) =
12250
12250
  init.body = Readable.toWeb(incoming);
12251
12251
  }
12252
12252
  }
12253
- return new Request(url, init);
12253
+ return new Request2(url, init);
12254
12254
  };
12255
12255
  var getRequestCache = /* @__PURE__ */ Symbol("getRequestCache");
12256
12256
  var requestCache = /* @__PURE__ */ Symbol("requestCache");
@@ -12311,7 +12311,7 @@ var requestPrototype = {
12311
12311
  }
12312
12312
  });
12313
12313
  });
12314
- Object.setPrototypeOf(requestPrototype, Request.prototype);
12314
+ Object.setPrototypeOf(requestPrototype, Request2.prototype);
12315
12315
  var newRequest = (incoming, defaultHostname) => {
12316
12316
  const req = Object.create(requestPrototype);
12317
12317
  req[incomingKey] = incoming;
@@ -12622,9 +12622,9 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
12622
12622
  };
12623
12623
  var getRequestListener = (fetchCallback, options = {}) => {
12624
12624
  const autoCleanupIncoming = options.autoCleanupIncoming ?? true;
12625
- if (options.overrideGlobalObjects !== false && global.Request !== Request) {
12625
+ if (options.overrideGlobalObjects !== false && global.Request !== Request2) {
12626
12626
  Object.defineProperty(global, "Request", {
12627
- value: Request
12627
+ value: Request2
12628
12628
  });
12629
12629
  Object.defineProperty(global, "Response", {
12630
12630
  value: Response2
@@ -13999,14 +13999,17 @@ var App = class {
13999
13999
  return this.resources;
14000
14000
  }
14001
14001
  /**
14002
- * Create a Vercel MCP adapter configuration.
14003
- * For use with Vercel's `mcp-handler` package.
14002
+ * Create a Vercel serverless function handler.
14003
+ * Works with plain Vercel Serverless Functions - no Next.js or mcp-handler needed.
14004
14004
  *
14005
- * Note: This returns a configuration callback. The implementation
14006
- * is inline to avoid circular dependencies.
14005
+ * Usage in api/mcp.ts:
14006
+ * ```ts
14007
+ * import { app } from "../src/app";
14008
+ * export default app.toVercelFunctionHandler();
14009
+ * ```
14007
14010
  */
14008
- toVercelMcp(options) {
14009
- return this.createServerlessConfig(options);
14011
+ toVercelFunctionHandler(options) {
14012
+ return this.createVercelHandler(options);
14010
14013
  }
14011
14014
  /**
14012
14015
  * Create an AWS Lambda handler.
@@ -14133,41 +14136,200 @@ var App = class {
14133
14136
  };
14134
14137
  }
14135
14138
  /**
14136
- * Create a Vercel MCP configuration callback.
14137
- * Returns a function compatible with Vercel's mcp-handler createMcpHandler.
14139
+ * Create a Vercel serverless function handler.
14140
+ * Handles MCP JSON-RPC protocol directly - no mcp-handler or Next.js needed.
14138
14141
  */
14139
- createServerlessConfig(options) {
14142
+ createVercelHandler(options) {
14140
14143
  const { stateAdapter, realtimeAdapter } = options || {};
14141
14144
  const app = this;
14142
- return function mcpConfig(server, _context) {
14143
- for (const [name, definition] of app.tools) {
14144
- const { config: toolConfig, handler } = definition;
14145
- const inputSchema = toolConfig.input || z2.object({});
14146
- const hasUi = !!toolConfig.ui;
14147
- server.registerTool(
14145
+ const corsHeaders = {
14146
+ "Access-Control-Allow-Origin": "*",
14147
+ "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
14148
+ "Access-Control-Allow-Headers": "Content-Type, Accept, Mcp-Session-Id",
14149
+ "Content-Type": "application/json"
14150
+ };
14151
+ return async (reqOrRequest, res) => {
14152
+ const isEdge = reqOrRequest instanceof Request;
14153
+ if (isEdge ? reqOrRequest.method === "OPTIONS" : reqOrRequest.method === "OPTIONS") {
14154
+ if (isEdge) {
14155
+ return new Response(null, { status: 204, headers: corsHeaders });
14156
+ }
14157
+ res.status(204).end();
14158
+ return;
14159
+ }
14160
+ let body = {};
14161
+ try {
14162
+ if (isEdge) {
14163
+ body = await reqOrRequest.json();
14164
+ } else if (reqOrRequest.body) {
14165
+ body = typeof reqOrRequest.body === "string" ? JSON.parse(reqOrRequest.body) : reqOrRequest.body;
14166
+ }
14167
+ } catch {
14168
+ const errorResponse = { jsonrpc: "2.0", error: { code: -32700, message: "Parse error" }, id: null };
14169
+ if (isEdge) {
14170
+ return new Response(JSON.stringify(errorResponse), { status: 400, headers: corsHeaders });
14171
+ }
14172
+ res.status(400).json(errorResponse);
14173
+ return;
14174
+ }
14175
+ try {
14176
+ const result = await app.handleMcpRequest(body, { stateAdapter, realtimeAdapter });
14177
+ if (isEdge) {
14178
+ return new Response(JSON.stringify(result), { status: 200, headers: corsHeaders });
14179
+ }
14180
+ res.status(200).json(result);
14181
+ } catch (error) {
14182
+ const err = error instanceof Error ? error : new Error(String(error));
14183
+ const errorResponse = { jsonrpc: "2.0", error: { code: -32603, message: err.message }, id: body.id ?? null };
14184
+ if (isEdge) {
14185
+ return new Response(JSON.stringify(errorResponse), { status: 500, headers: corsHeaders });
14186
+ }
14187
+ res.status(500).json(errorResponse);
14188
+ }
14189
+ };
14190
+ }
14191
+ /**
14192
+ * Handle an MCP JSON-RPC request.
14193
+ * Shared logic for all serverless handlers.
14194
+ */
14195
+ async handleMcpRequest(body, options) {
14196
+ const { stateAdapter, realtimeAdapter } = options;
14197
+ const method = body.method;
14198
+ const params = body.params;
14199
+ const id = body.id;
14200
+ if (method === "initialize") {
14201
+ return {
14202
+ jsonrpc: "2.0",
14203
+ result: {
14204
+ protocolVersion: "2024-11-05",
14205
+ serverInfo: { name: this.config.name, version: this.config.version },
14206
+ capabilities: { tools: {}, resources: {} },
14207
+ ...this.config.instructions && { instructions: this.config.instructions }
14208
+ },
14209
+ id
14210
+ };
14211
+ }
14212
+ if (method === "tools/list") {
14213
+ const tools = [];
14214
+ for (const [name, definition] of this.tools) {
14215
+ const { config } = definition;
14216
+ const toolMeta = this.buildToolMeta(config);
14217
+ tools.push({
14148
14218
  name,
14149
- {
14150
- title: name,
14151
- description: toolConfig.description + (hasUi ? " Returns instanceId for the widget." : ""),
14152
- inputSchema
14219
+ description: this.buildToolDescription(config, config.input || z2.object({})),
14220
+ inputSchema: config.input ? this.zodToJsonSchema(config.input) : { type: "object" },
14221
+ ...Object.keys(toolMeta).length > 0 && { _meta: toolMeta }
14222
+ });
14223
+ }
14224
+ return { jsonrpc: "2.0", result: { tools }, id };
14225
+ }
14226
+ if (method === "tools/call") {
14227
+ const toolName = params?.name;
14228
+ const args = params?.arguments || {};
14229
+ const definition = this.tools.get(toolName);
14230
+ if (!definition) {
14231
+ return { jsonrpc: "2.0", error: { code: -32601, message: `Tool not found: ${toolName}` }, id };
14232
+ }
14233
+ const { config: toolConfig, handler } = definition;
14234
+ const creatureToken = args._creatureToken;
14235
+ const { _creatureToken: _, ...cleanArgs } = args;
14236
+ const input = toolConfig.input ? toolConfig.input.parse(cleanArgs) : cleanArgs;
14237
+ const instanceId = cleanArgs.instanceId || this.generateInstanceId();
14238
+ const context = this.createServerlessContext({ instanceId, creatureToken, stateAdapter, realtimeAdapter });
14239
+ const result = await handler(input, context);
14240
+ const formatted = this.formatServerlessResult(result, instanceId, context.websocketUrl);
14241
+ return { jsonrpc: "2.0", result: formatted, id };
14242
+ }
14243
+ if (method === "resources/list") {
14244
+ const resources = [];
14245
+ for (const [uri, { config }] of this.resources) {
14246
+ resources.push({
14247
+ uri,
14248
+ name: config.name,
14249
+ description: config.description,
14250
+ mimeType: MIME_TYPES.MCP_APPS
14251
+ });
14252
+ }
14253
+ return { jsonrpc: "2.0", result: { resources }, id };
14254
+ }
14255
+ if (method === "resources/read") {
14256
+ const uri = params?.uri;
14257
+ const resourceDef = this.resources.get(uri);
14258
+ if (!resourceDef) {
14259
+ return { jsonrpc: "2.0", error: { code: -32601, message: `Resource not found: ${uri}` }, id };
14260
+ }
14261
+ const { config } = resourceDef;
14262
+ let html = typeof config.html === "function" ? await config.html() : config.html;
14263
+ const mcpAppsMeta = {
14264
+ ui: {
14265
+ displayModes: config.displayModes,
14266
+ ...config.icon && {
14267
+ icon: {
14268
+ data: svgToDataUri(config.icon.svg),
14269
+ alt: config.icon.alt
14270
+ }
14153
14271
  },
14154
- async (args) => {
14155
- try {
14156
- const creatureToken = args._creatureToken;
14157
- const { _creatureToken: _, ...cleanArgs } = args;
14158
- const input = toolConfig.input ? toolConfig.input.parse(cleanArgs) : cleanArgs;
14159
- const instanceId = cleanArgs.instanceId || app.generateInstanceId();
14160
- const context = app.createServerlessContext({ instanceId, creatureToken, stateAdapter, realtimeAdapter });
14161
- const result = await handler(input, context);
14162
- return app.formatServerlessResult(result, instanceId, context.websocketUrl);
14163
- } catch (error) {
14164
- const err = error instanceof Error ? error : new Error(String(error));
14165
- return { content: [{ type: "text", text: err.message }], isError: true };
14272
+ ...config.csp && { csp: config.csp }
14273
+ },
14274
+ "openai/widgetPrefersBorder": true
14275
+ };
14276
+ return {
14277
+ jsonrpc: "2.0",
14278
+ result: {
14279
+ contents: [
14280
+ {
14281
+ uri,
14282
+ mimeType: MIME_TYPES.MCP_APPS,
14283
+ text: html,
14284
+ _meta: mcpAppsMeta
14285
+ }
14286
+ ]
14287
+ },
14288
+ id
14289
+ };
14290
+ }
14291
+ return { jsonrpc: "2.0", error: { code: -32601, message: `Method not found: ${method}` }, id };
14292
+ }
14293
+ /**
14294
+ * Convert Zod schema to JSON Schema for tool definitions.
14295
+ */
14296
+ zodToJsonSchema(schema) {
14297
+ if ("_def" in schema) {
14298
+ const def = schema._def;
14299
+ if (def.typeName === "ZodObject") {
14300
+ const shape = def.shape?.() || {};
14301
+ const properties = {};
14302
+ const required = [];
14303
+ for (const [key, value] of Object.entries(shape)) {
14304
+ const fieldDef = value._def;
14305
+ if (fieldDef?.typeName === "ZodString") {
14306
+ properties[key] = { type: "string", description: fieldDef.description };
14307
+ } else if (fieldDef?.typeName === "ZodNumber") {
14308
+ properties[key] = { type: "number", description: fieldDef.description };
14309
+ } else if (fieldDef?.typeName === "ZodBoolean") {
14310
+ properties[key] = { type: "boolean", description: fieldDef.description };
14311
+ } else if (fieldDef?.typeName === "ZodOptional") {
14312
+ const inner = fieldDef.innerType?._def;
14313
+ if (inner?.typeName === "ZodString") {
14314
+ properties[key] = { type: "string", description: inner.description };
14315
+ } else {
14316
+ properties[key] = { type: "string" };
14166
14317
  }
14318
+ } else {
14319
+ properties[key] = { type: "string" };
14167
14320
  }
14168
- );
14321
+ if (fieldDef?.typeName !== "ZodOptional") {
14322
+ required.push(key);
14323
+ }
14324
+ }
14325
+ return {
14326
+ type: "object",
14327
+ properties,
14328
+ ...required.length > 0 && { required }
14329
+ };
14169
14330
  }
14170
- };
14331
+ }
14332
+ return { type: "object" };
14171
14333
  }
14172
14334
  /**
14173
14335
  * Create an AWS Lambda handler function.
@@ -14175,13 +14337,13 @@ var App = class {
14175
14337
  createLambdaHandler(options) {
14176
14338
  const { stateAdapter, realtimeAdapter } = options || {};
14177
14339
  const app = this;
14340
+ const corsHeaders = {
14341
+ "Access-Control-Allow-Origin": "*",
14342
+ "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
14343
+ "Access-Control-Allow-Headers": "Content-Type, Accept, Mcp-Session-Id",
14344
+ "Content-Type": "application/json"
14345
+ };
14178
14346
  return async (event, _lambdaContext) => {
14179
- const corsHeaders = {
14180
- "Access-Control-Allow-Origin": "*",
14181
- "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
14182
- "Access-Control-Allow-Headers": "Content-Type, Accept, Mcp-Session-Id",
14183
- "Content-Type": "application/json"
14184
- };
14185
14347
  if (event.httpMethod === "OPTIONS") {
14186
14348
  return { statusCode: 204, headers: corsHeaders, body: "" };
14187
14349
  }
@@ -14200,68 +14362,11 @@ var App = class {
14200
14362
  }
14201
14363
  }
14202
14364
  try {
14203
- const method = body.method;
14204
- const params = body.params;
14205
- const id = body.id;
14206
- if (method === "initialize") {
14207
- return {
14208
- statusCode: 200,
14209
- headers: corsHeaders,
14210
- body: JSON.stringify({
14211
- jsonrpc: "2.0",
14212
- result: {
14213
- protocolVersion: "2024-11-05",
14214
- serverInfo: { name: app.config.name, version: app.config.version },
14215
- capabilities: { tools: {}, resources: {} }
14216
- },
14217
- id
14218
- })
14219
- };
14220
- }
14221
- if (method === "tools/list") {
14222
- const tools = [];
14223
- for (const [name, definition] of app.tools) {
14224
- tools.push({
14225
- name,
14226
- description: definition.config.description,
14227
- inputSchema: { type: "object" }
14228
- });
14229
- }
14230
- return {
14231
- statusCode: 200,
14232
- headers: corsHeaders,
14233
- body: JSON.stringify({ jsonrpc: "2.0", result: { tools }, id })
14234
- };
14235
- }
14236
- if (method === "tools/call") {
14237
- const toolName = params?.name;
14238
- const args = params?.arguments || {};
14239
- const definition = app.tools.get(toolName);
14240
- if (!definition) {
14241
- return {
14242
- statusCode: 200,
14243
- headers: corsHeaders,
14244
- body: JSON.stringify({ jsonrpc: "2.0", error: { code: -32601, message: `Tool not found: ${toolName}` }, id })
14245
- };
14246
- }
14247
- const { config: toolConfig, handler } = definition;
14248
- const creatureToken = args._creatureToken;
14249
- const { _creatureToken: _, ...cleanArgs } = args;
14250
- const input = toolConfig.input ? toolConfig.input.parse(cleanArgs) : cleanArgs;
14251
- const instanceId = cleanArgs.instanceId || app.generateInstanceId();
14252
- const context = app.createServerlessContext({ instanceId, creatureToken, stateAdapter, realtimeAdapter });
14253
- const result = await handler(input, context);
14254
- const formatted = app.formatServerlessResult(result, instanceId, context.websocketUrl);
14255
- return {
14256
- statusCode: 200,
14257
- headers: corsHeaders,
14258
- body: JSON.stringify({ jsonrpc: "2.0", result: formatted, id })
14259
- };
14260
- }
14365
+ const result = await app.handleMcpRequest(body, { stateAdapter, realtimeAdapter });
14261
14366
  return {
14262
14367
  statusCode: 200,
14263
14368
  headers: corsHeaders,
14264
- body: JSON.stringify({ jsonrpc: "2.0", error: { code: -32601, message: `Method not found: ${method}` }, id })
14369
+ body: JSON.stringify(result)
14265
14370
  };
14266
14371
  } catch (error) {
14267
14372
  const err = error instanceof Error ? error : new Error(String(error));