@joai/warps-mcp 1.0.0-beta.35 → 1.0.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.cts CHANGED
@@ -11,8 +11,29 @@ type WarpMcpServerConfig = {
11
11
  type JsonSchema$1 = Record<string, unknown>;
12
12
  type ToolInputSchema = Record<string, z.ZodTypeAny> | JsonSchema$1 | undefined;
13
13
  type ToolOutputSchema = JsonSchema$1 | undefined;
14
- type ToolMeta = Record<string, string | number | boolean | null>;
15
- type ResourceMeta = Record<string, unknown>;
14
+ type WarpAppUiMeta = {
15
+ resourceUri?: string;
16
+ visibility?: string[];
17
+ };
18
+ type WarpAppResourceUiMeta = {
19
+ csp?: {
20
+ resourceDomains?: string[];
21
+ connectDomains?: string[];
22
+ frameDomains?: string[];
23
+ baseUriDomains?: string[];
24
+ };
25
+ permissions?: ('camera' | 'microphone' | 'geolocation' | 'clipboard')[];
26
+ domain?: string;
27
+ prefersBorder?: boolean;
28
+ };
29
+ type ToolMeta = {
30
+ ui?: WarpAppUiMeta;
31
+ [key: string]: string | number | boolean | null | WarpAppUiMeta | undefined;
32
+ };
33
+ type ResourceMeta = {
34
+ ui?: WarpAppResourceUiMeta;
35
+ [key: string]: unknown;
36
+ };
16
37
  type WarpMcpTool = {
17
38
  name: string;
18
39
  description?: string;
@@ -93,4 +114,4 @@ declare class WarpMcp {
93
114
  getWarpsFromTools(url: string, headers?: Record<string, string>): Promise<Warp[]>;
94
115
  }
95
116
 
96
- export { type JsonSchema$1 as JsonSchema, type ResourceMeta, type ToolInputSchema, type ToolMeta, type ToolOutputSchema, WarpMcp, type WarpMcpCapabilities, type WarpMcpExecutor, type WarpMcpPrompt, type WarpMcpPromptArgument, type WarpMcpResource, type WarpMcpServerConfig, type WarpMcpTool, type WarpMcpToolArgs, type WarpMcpToolResult, buildZodInputSchema, convertActionToTool, convertMcpActionToTool, convertMcpArgsToWarpInputs, convertMcpToolToWarp, convertPromptActionToPrompt, convertWarpToMcpCapabilities, convertWarpsToMcpCapabilities, createAppResource, createMcpServerFromWarps, extractTextOrUndefined, interpolatePromptWithArgs };
117
+ export { type JsonSchema$1 as JsonSchema, type ResourceMeta, type ToolInputSchema, type ToolMeta, type ToolOutputSchema, type WarpAppResourceUiMeta, type WarpAppUiMeta, WarpMcp, type WarpMcpCapabilities, type WarpMcpExecutor, type WarpMcpPrompt, type WarpMcpPromptArgument, type WarpMcpResource, type WarpMcpServerConfig, type WarpMcpTool, type WarpMcpToolArgs, type WarpMcpToolResult, buildZodInputSchema, convertActionToTool, convertMcpActionToTool, convertMcpArgsToWarpInputs, convertMcpToolToWarp, convertPromptActionToPrompt, convertWarpToMcpCapabilities, convertWarpsToMcpCapabilities, createAppResource, createMcpServerFromWarps, extractTextOrUndefined, interpolatePromptWithArgs };
package/dist/index.d.ts CHANGED
@@ -11,8 +11,29 @@ type WarpMcpServerConfig = {
11
11
  type JsonSchema$1 = Record<string, unknown>;
12
12
  type ToolInputSchema = Record<string, z.ZodTypeAny> | JsonSchema$1 | undefined;
13
13
  type ToolOutputSchema = JsonSchema$1 | undefined;
14
- type ToolMeta = Record<string, string | number | boolean | null>;
15
- type ResourceMeta = Record<string, unknown>;
14
+ type WarpAppUiMeta = {
15
+ resourceUri?: string;
16
+ visibility?: string[];
17
+ };
18
+ type WarpAppResourceUiMeta = {
19
+ csp?: {
20
+ resourceDomains?: string[];
21
+ connectDomains?: string[];
22
+ frameDomains?: string[];
23
+ baseUriDomains?: string[];
24
+ };
25
+ permissions?: ('camera' | 'microphone' | 'geolocation' | 'clipboard')[];
26
+ domain?: string;
27
+ prefersBorder?: boolean;
28
+ };
29
+ type ToolMeta = {
30
+ ui?: WarpAppUiMeta;
31
+ [key: string]: string | number | boolean | null | WarpAppUiMeta | undefined;
32
+ };
33
+ type ResourceMeta = {
34
+ ui?: WarpAppResourceUiMeta;
35
+ [key: string]: unknown;
36
+ };
16
37
  type WarpMcpTool = {
17
38
  name: string;
18
39
  description?: string;
@@ -93,4 +114,4 @@ declare class WarpMcp {
93
114
  getWarpsFromTools(url: string, headers?: Record<string, string>): Promise<Warp[]>;
94
115
  }
95
116
 
96
- export { type JsonSchema$1 as JsonSchema, type ResourceMeta, type ToolInputSchema, type ToolMeta, type ToolOutputSchema, WarpMcp, type WarpMcpCapabilities, type WarpMcpExecutor, type WarpMcpPrompt, type WarpMcpPromptArgument, type WarpMcpResource, type WarpMcpServerConfig, type WarpMcpTool, type WarpMcpToolArgs, type WarpMcpToolResult, buildZodInputSchema, convertActionToTool, convertMcpActionToTool, convertMcpArgsToWarpInputs, convertMcpToolToWarp, convertPromptActionToPrompt, convertWarpToMcpCapabilities, convertWarpsToMcpCapabilities, createAppResource, createMcpServerFromWarps, extractTextOrUndefined, interpolatePromptWithArgs };
117
+ export { type JsonSchema$1 as JsonSchema, type ResourceMeta, type ToolInputSchema, type ToolMeta, type ToolOutputSchema, type WarpAppResourceUiMeta, type WarpAppUiMeta, WarpMcp, type WarpMcpCapabilities, type WarpMcpExecutor, type WarpMcpPrompt, type WarpMcpPromptArgument, type WarpMcpResource, type WarpMcpServerConfig, type WarpMcpTool, type WarpMcpToolArgs, type WarpMcpToolResult, buildZodInputSchema, convertActionToTool, convertMcpActionToTool, convertMcpArgsToWarpInputs, convertMcpToolToWarp, convertPromptActionToPrompt, convertWarpToMcpCapabilities, convertWarpsToMcpCapabilities, createAppResource, createMcpServerFromWarps, extractTextOrUndefined, interpolatePromptWithArgs };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var T=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var N=(e,r)=>{for(var t in r)T(e,t,{get:r[t],enumerable:!0})},U=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of E(r))!O.call(e,o)&&o!==t&&T(e,o,{get:()=>r[o],enumerable:!(n=q(r,o))||n.enumerable});return e};var D=e=>U(T({},"__esModule",{value:!0}),e);var ee={};N(ee,{WarpMcp:()=>v,buildZodInputSchema:()=>h,convertActionToTool:()=>M,convertMcpActionToTool:()=>C,convertMcpArgsToWarpInputs:()=>A,convertMcpToolToWarp:()=>P,convertPromptActionToPrompt:()=>R,convertWarpToMcpCapabilities:()=>w,convertWarpsToMcpCapabilities:()=>H,createAppResource:()=>x,createMcpServerFromWarps:()=>Y,extractTextOrUndefined:()=>l,interpolatePromptWithArgs:()=>S});module.exports=D(ee);var W=require("@joai/warps"),A=(e,r)=>{let{action:t}=(0,W.getWarpPrimaryAction)(e);if(!t.inputs)return[];let n=new W.WarpSerializer;return t.inputs.map(o=>{let i=o.as||o.name,p=r[i]??o.default??null;return p===null&&o.type==="bool"?n.nativeToString(o.type,!1):n.nativeToString(o.type,p)})};var d=require("@joai/warps");var I=require("@joai/warps"),m=require("zod");var J=e=>{if(e){if(Array.isArray(e))return e;if(typeof e=="object")return Object.keys(e)}},F=(e,r)=>{let t,n=e.type.toLowerCase();n==="string"||n==="address"||n==="hex"?t=m.z.string():n==="number"||n==="uint8"||n==="uint16"||n==="uint32"||n==="uint64"||n==="uint128"||n==="uint256"?t=m.z.number():n==="bool"||n==="boolean"?t=m.z.boolean():n==="biguint"?t=m.z.string():t=m.z.string(),typeof e.min=="number"&&t instanceof m.z.ZodNumber&&(t=t.min(e.min)),typeof e.max=="number"&&t instanceof m.z.ZodNumber&&(t=t.max(e.max)),e.pattern&&t instanceof m.z.ZodString&&(t=t.regex(new RegExp(e.pattern)));let o=J(e.options);if(o&&o.length>0){if(t instanceof m.z.ZodString)t=m.z.enum(o);else if(t instanceof m.z.ZodNumber){let u=o.map(a=>Number(a)).filter(a=>!isNaN(a));u.length>0&&(t=t.refine(a=>u.includes(a),{message:`Value must be one of: ${u.join(", ")}`}))}}let i=[],p=l(e.description,r);p&&i.push(p),e.bot&&i.push(e.bot),i.push(`Type: ${e.type}`),i.push(e.required?"Required":"Optional"),o&&o.length>0&&i.push(`Options: ${o.join(", ")}`);let s=l(e.patternDescription,r);s&&i.push(s);let c=i.join(". ");return c&&(t=t.describe(c)),e.required!==!0&&(t=t.optional()),t},h=(e,r)=>{let t={};for(let n of e){if(n.source==="hidden"||n.source!=="field")continue;let o=n.as||n.name;t[o]=F(n,r)}return Object.keys(t).length>0?t:void 0},M=(e,r,t,n,o,i)=>{let p=L(e),s=n||r.inputs||[],c=h(s,i);return{name:p,description:t,inputSchema:c,meta:z(e,o,i)}},C=(e,r,t,n,o,i)=>{let p=n||r.inputs||[],s=h(p,i),c=r.destination?.tool;if(!c)throw new Error(`Tool name is required for MCP action ${r.type}`);return{name:c,description:t,inputSchema:s,meta:z(e,o,i)}},z=(e,r,t)=>{let n={"openai/widgetAccessible":!0};if(r&&(n["openai/outputTemplate"]=r.uri),e.messages){let o=l(e.messages.invoking,t),i=l(e.messages.invoked,t);o&&(n["openai/toolInvocation/invoking"]=o),i&&(n["openai/toolInvocation/invoked"]=i)}return n},L=e=>{let r=e.meta?.identifier;if(!r)throw new Error(`Warp identifier for warp ${e.name} is required`);return(0,I.cleanWarpIdentifier)(r).replace(":",".")};var b=require("@joai/warps"),V=async e=>{if(e.startsWith("http://")||e.startsWith("https://")){let r=await fetch(e);if(!r.ok)throw new Error(`Failed to download component from ${e}: HTTP ${r.status} ${r.statusText}`);return r.text()}throw new Error(`Unsupported component path: ${e}`)},x=async(e,r,t)=>{if(!e.meta?.identifier)return null;try{let n=await V(r);return{name:e.name,uri:`ui://widget/${e.meta.identifier}`,description:`ChatGPT app for ${e.name}`,mimeType:"text/html+skybridge",content:n}}catch(n){let o=n instanceof Error?n.message:String(n),i=n instanceof Error?n.stack:void 0;return b.WarpLogger.error(`[MCP] Failed to create app resource for warp "${e.name}" (path: ${r}):`,o),i&&b.WarpLogger.error("[MCP] Error stack:",i),null}};var w=async(e,r)=>{let t=null,n=null,o=null;if(e.ui&&e.ui!=="table"&&(n=await x(e,e.ui,r)),e.actions.length===0)return{tool:null,resource:n,prompt:null};try{let{action:i}=(0,d.getWarpPrimaryAction)(e),p=l(e.description,r)||l(i.description,r);if(i.type==="prompt")o=R(e,i,p,r);else if(i.type==="mcp"){let s=i;s.destination&&(t=C(e,s,p,i.inputs,n,r))}else t=M(e,i,p,i.inputs,n,r)}catch{return{tool:null,resource:n,prompt:null}}return{tool:t,resource:n,prompt:o}},H=async(e,r)=>Promise.all(e.map(t=>w(t,r))),Q=(e,r)=>r==="date-time"||r==="date"||e==="string"?"string":e==="number"||e==="integer"?"uint256":e==="boolean"?"bool":"string",P=async(e,r,t,n)=>{let o=[];if(r.inputSchema?.properties){let s=r.inputSchema.properties,c=r.inputSchema.required||[];Object.entries(s).forEach(([u,a])=>{let f=c.includes(u),g=Q(a.type||"string",a.format),y={name:u,label:typeof a.title=="string"?{en:a.title}:a.title||{en:u},description:a.description?{en:a.description.trim()}:null,type:g,position:`payload:${u}`,source:"field",required:f,...a.default!==void 0&&typeof a.default=="string"||typeof a.default=="number"||typeof a.default=="boolean"?{default:a.default}:{}};o.push(y)})}let i={};r.outputSchema?.properties&&Object.keys(r.outputSchema.properties).forEach(s=>{i[s]=`out.${s}`});let p={type:"mcp",label:{en:r.name},description:r.description?{en:r.description.trim()}:null,destination:{url:t,tool:r.name,headers:n},inputs:o};return await new d.WarpBuilder(e).setName(r.name||"unnamed_tool").setTitle({en:r.name||"Unnamed Tool"}).setDescription(r.description?{en:r.description.trim()}:null).addAction(p).setOutput(Object.keys(i).length>0?i:null).build(!1)},l=(e,r)=>e&&(0,d.resolveWarpText)(e,r)||void 0;var S=(e,r)=>{let t=e;for(let[n,o]of Object.entries(r)){let i=new RegExp(`\\{\\{\\s*${n}\\s*\\}\\}`,"g");t=t.replace(i,o??"")}return t},B=e=>(e.includes(":")?e.split(":").slice(1).join(":"):e).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,r=>r.includes("_")?"_":r).replace(/_+/g,"_"),G=(e,r)=>{let t=[];for(let n of e){if(n.source==="hidden"||n.source!=="field")continue;let o=n.as||n.name,i=l(n.description,r);t.push({name:o,description:i,required:n.required===!0})}return t},R=(e,r,t,n)=>{let o=B(e.name),i=r.inputs||[],p=G(i,n);return{name:o,description:t,arguments:p.length>0?p:void 0,prompt:r.prompt}};var Z=require("@modelcontextprotocol/sdk/server/mcp.js"),k=require("@modelcontextprotocol/sdk/server/zod-compat.js"),$=require("zod");var K=e=>{if(e)return typeof e=="object"&&"_zod"in e?e._zod:typeof e=="object"&&!Array.isArray(e)&&(0,k.normalizeObjectSchema)(e)||e},X=e=>{if(!e.arguments||e.arguments.length===0)return;let r={};for(let t of e.arguments){let n=$.z.string();t.description&&(n=n.describe(t.description)),t.required||(n=n.optional()),r[t.name]=n}return r},Y=(e,r,t,n)=>{let o=new Z.McpServer({name:e.name,version:e.version||"1.0.0"});for(let i=0;i<t.length;i++){let{tool:p,resource:s,prompt:c}=t[i],u=r[i];if(p){let a=K(p.inputSchema),f={description:p.description||"",inputSchema:a,...p.meta&&{_meta:p.meta}};o.registerTool(p.name,f,async g=>{let y=A(u,g||{});return await n(u,y)})}if(s&&o.registerResource(s.name||s.uri,s.uri,{description:s.description,mimeType:s.mimeType},async()=>{let a={uri:s.uri,text:s.content||"",mimeType:s.mimeType};return s.meta&&(a._meta=s.meta),{contents:[a]}}),c){let a=X(c);o.registerPrompt(c.name,{description:c.description||"",argsSchema:a},f=>({messages:[{role:"user",content:{type:"text",text:S(c.prompt,f)}}]}))}}return o};var j=require("@modelcontextprotocol/sdk/client/index.js"),_=require("@modelcontextprotocol/sdk/client/streamableHttp.js");var v=class{constructor(r){this.config=r}async getWarpsFromTools(r,t){let n=new _.StreamableHTTPClientTransport(new URL(r),{requestInit:{headers:t||{}}}),o=new j.Client({name:"warps-mcp-client",version:"1.0.0"},{capabilities:{}});try{await o.connect(n);let i=await o.listTools();return await o.close(),await Promise.all(i.tools.map(p=>P(this.config,p,r,t)))}catch(i){throw await o.close().catch(()=>{}),i}}};0&&(module.exports={WarpMcp,buildZodInputSchema,convertActionToTool,convertMcpActionToTool,convertMcpArgsToWarpInputs,convertMcpToolToWarp,convertPromptActionToPrompt,convertWarpToMcpCapabilities,convertWarpsToMcpCapabilities,createAppResource,createMcpServerFromWarps,extractTextOrUndefined,interpolatePromptWithArgs});
1
+ "use strict";var A=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var D=(e,r)=>{for(var t in r)A(e,t,{get:r[t],enumerable:!0})},J=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of N(r))!U.call(e,o)&&o!==t&&A(e,o,{get:()=>r[o],enumerable:!(n=k(r,o))||n.enumerable});return e};var F=e=>J(A({},"__esModule",{value:!0}),e);var ne={};D(ne,{WarpMcp:()=>z,buildZodInputSchema:()=>h,convertActionToTool:()=>C,convertMcpActionToTool:()=>b,convertMcpArgsToWarpInputs:()=>M,convertMcpToolToWarp:()=>R,convertPromptActionToPrompt:()=>S,convertWarpToMcpCapabilities:()=>Z,convertWarpsToMcpCapabilities:()=>Y,createAppResource:()=>P,createMcpServerFromWarps:()=>te,extractTextOrUndefined:()=>l,interpolatePromptWithArgs:()=>I});module.exports=F(ne);var W=require("@joai/warps"),M=(e,r)=>{let{action:t}=(0,W.getWarpPrimaryAction)(e);if(!t.inputs)return[];let n=new W.WarpSerializer;return t.inputs.map(o=>{let i=o.as||o.name,s=r[i]??o.default??null;return s===null&&o.type==="bool"?n.nativeToString(o.type,!1):n.nativeToString(o.type,s)})};var d=require("@joai/warps");var w=require("@joai/warps"),m=require("zod");var L=e=>{if(e){if(Array.isArray(e))return e;if(typeof e=="object")return Object.keys(e)}},V=(e,r)=>{let t,n=e.type.toLowerCase();n==="string"||n==="address"||n==="hex"?t=m.z.string():n==="number"||n==="uint8"||n==="uint16"||n==="uint32"||n==="uint64"||n==="uint128"||n==="uint256"?t=m.z.number():n==="bool"||n==="boolean"?t=m.z.boolean():n==="biguint"?t=m.z.string():t=m.z.string(),typeof e.min=="number"&&t instanceof m.z.ZodNumber&&(t=t.min(e.min)),typeof e.max=="number"&&t instanceof m.z.ZodNumber&&(t=t.max(e.max)),e.pattern&&t instanceof m.z.ZodString&&(t=t.regex(new RegExp(e.pattern)));let o=L(e.options);if(o&&o.length>0){if(t instanceof m.z.ZodString)t=m.z.enum(o);else if(t instanceof m.z.ZodNumber){let u=o.map(a=>Number(a)).filter(a=>!isNaN(a));u.length>0&&(t=t.refine(a=>u.includes(a),{message:`Value must be one of: ${u.join(", ")}`}))}}let i=[],s=l(e.description,r);s&&i.push(s),e.bot&&i.push(e.bot),i.push(`Type: ${e.type}`),i.push(e.required?"Required":"Optional"),o&&o.length>0&&i.push(`Options: ${o.join(", ")}`);let p=l(e.patternDescription,r);p&&i.push(p);let c=i.join(". ");return c&&(t=t.describe(c)),e.required!==!0&&(t=t.optional()),t},h=(e,r)=>{let t={};for(let n of e){if(n.source==="hidden"||n.source!=="field")continue;let o=n.as||n.name;t[o]=V(n,r)}return Object.keys(t).length>0?t:void 0},C=(e,r,t,n,o,i)=>{let s=H(e),p=n||r.inputs||[],c=h(p,i);return{name:s,description:t,inputSchema:c,meta:v(e,o,i)}},b=(e,r,t,n,o,i)=>{let s=n||r.inputs||[],p=h(s,i),c=r.destination?.tool;if(!c)throw new Error(`Tool name is required for MCP action ${r.type}`);return{name:c,description:t,inputSchema:p,meta:v(e,o,i)}},v=(e,r,t)=>{let n={visibility:["model","app"]};return r&&(n.resourceUri=r.uri),{ui:n}},H=e=>{let r=e.meta?.identifier;if(!r)throw new Error(`Warp identifier for warp ${e.name} is required`);return(0,w.cleanWarpIdentifier)(r).replace(":",".")};var x=require("@joai/warps"),Q="text/html;profile=mcp-app",B=async e=>{if(e.startsWith("http://")||e.startsWith("https://")){let r=await fetch(e);if(!r.ok)throw new Error(`Failed to download component from ${e}: HTTP ${r.status} ${r.statusText}`);return r.text()}throw new Error(`Unsupported component path: ${e}`)},P=async(e,r,t)=>{if(!e.meta?.identifier)return null;try{let n=await B(r);return{name:e.name,uri:`ui://widget/${e.meta.identifier}`,description:`MCP app for ${e.name}`,mimeType:Q,content:n}}catch(n){let o=n instanceof Error?n.message:String(n),i=n instanceof Error?n.stack:void 0;return x.WarpLogger.error(`[MCP] Failed to create app resource for warp "${e.name}" (path: ${r}):`,o),i&&x.WarpLogger.error("[MCP] Error stack:",i),null}};var Z=async(e,r)=>{let t=null,n=null,o=null;if(e.ui&&e.ui!=="table"&&(n=await P(e,e.ui,r)),e.actions.length===0)return{tool:null,resource:n,prompt:null};try{let{action:i}=(0,d.getWarpPrimaryAction)(e),s=l(e.description,r)||l(i.description,r);if(i.type==="prompt")o=S(e,i,s,r);else if(i.type==="mcp"){let p=i;p.destination&&(t=b(e,p,s,i.inputs,n,r))}else t=C(e,i,s,i.inputs,n,r)}catch{return{tool:null,resource:n,prompt:null}}return{tool:t,resource:n,prompt:o}},Y=async(e,r)=>Promise.all(e.map(t=>Z(t,r))),G=(e,r)=>r==="date-time"||r==="date"||e==="string"?"string":e==="number"||e==="integer"?"uint256":e==="boolean"?"bool":"string",R=async(e,r,t,n)=>{let o=[];if(r.inputSchema?.properties){let p=r.inputSchema.properties,c=r.inputSchema.required||[];Object.entries(p).forEach(([u,a])=>{let f=c.includes(u),g=G(a.type||"string",a.format),T={name:u,label:typeof a.title=="string"?{en:a.title}:a.title||{en:u},description:a.description?{en:a.description.trim()}:null,type:g,position:`payload:${u}`,source:"field",required:f,...a.default!==void 0&&typeof a.default=="string"||typeof a.default=="number"||typeof a.default=="boolean"?{default:a.default}:{}};o.push(T)})}let i={};r.outputSchema?.properties&&Object.keys(r.outputSchema.properties).forEach(p=>{i[p]=`out.${p}`});let s={type:"mcp",label:{en:r.name},description:r.description?{en:r.description.trim()}:null,destination:{url:t,tool:r.name,headers:n},inputs:o};return await new d.WarpBuilder(e).setName(r.name||"unnamed_tool").setTitle({en:r.name||"Unnamed Tool"}).setDescription(r.description?{en:r.description.trim()}:null).addAction(s).setOutput(Object.keys(i).length>0?i:null).build(!1)},l=(e,r)=>e&&(0,d.resolveWarpText)(e,r)||void 0;var I=(e,r)=>{let t=e;for(let[n,o]of Object.entries(r)){let i=new RegExp(`\\{\\{\\s*${n}\\s*\\}\\}`,"g");t=t.replace(i,o??"")}return t},K=e=>(e.includes(":")?e.split(":").slice(1).join(":"):e).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,r=>r.includes("_")?"_":r).replace(/_+/g,"_"),X=(e,r)=>{let t=[];for(let n of e){if(n.source==="hidden"||n.source!=="field")continue;let o=n.as||n.name,i=l(n.description,r);t.push({name:o,description:i,required:n.required===!0})}return t},S=(e,r,t,n)=>{let o=K(e.name),i=r.inputs||[],s=X(i,n);return{name:o,description:t,arguments:s.length>0?s:void 0,prompt:r.prompt}};var _=require("@modelcontextprotocol/sdk/server/mcp.js"),E=require("@modelcontextprotocol/sdk/server/zod-compat.js"),y=require("@modelcontextprotocol/ext-apps/server"),$=require("zod");var ee=e=>{if(e)return typeof e=="object"&&"_zod"in e?e._zod:typeof e=="object"&&!Array.isArray(e)&&(0,E.normalizeObjectSchema)(e)||e},re=e=>{if(!e.arguments||e.arguments.length===0)return;let r={};for(let t of e.arguments){let n=$.z.string();t.description&&(n=n.describe(t.description)),t.required||(n=n.optional()),r[t.name]=n}return r},te=(e,r,t,n)=>{let o=new _.McpServer({name:e.name,version:e.version||"1.0.0"});for(let i=0;i<t.length;i++){let{tool:s,resource:p,prompt:c}=t[i],u=r[i];if(s){let a=ee(s.inputSchema),f={description:s.description||"",inputSchema:a,...s.meta&&{_meta:s.meta}},g=async T=>{let q=M(u,T||{});return await n(u,q)};s.meta?.ui?.resourceUri?(0,y.registerAppTool)(o,s.name,f,g):o.registerTool(s.name,f,g)}if(p&&(p.mimeType?.includes("profile=mcp-app")?(0,y.registerAppResource)(o,p.name||p.uri,p.uri,{description:p.description},async()=>{let a={uri:p.uri,text:p.content||"",mimeType:p.mimeType};return p.meta&&(a._meta=p.meta),{contents:[a]}}):o.registerResource(p.name||p.uri,p.uri,{description:p.description,mimeType:p.mimeType},async()=>{let a={uri:p.uri,text:p.content||"",mimeType:p.mimeType};return p.meta&&(a._meta=p.meta),{contents:[a]}})),c){let a=re(c);o.registerPrompt(c.name,{description:c.description||"",argsSchema:a},f=>({messages:[{role:"user",content:{type:"text",text:I(c.prompt,f)}}]}))}}return o};var j=require("@modelcontextprotocol/sdk/client/index.js"),O=require("@modelcontextprotocol/sdk/client/streamableHttp.js");var z=class{constructor(r){this.config=r}async getWarpsFromTools(r,t){let n=new O.StreamableHTTPClientTransport(new URL(r),{requestInit:{headers:t||{}}}),o=new j.Client({name:"warps-mcp-client",version:"1.0.0"},{capabilities:{}});try{await o.connect(n);let i=await o.listTools();return await o.close(),await Promise.all(i.tools.map(s=>R(this.config,s,r,t)))}catch(i){throw await o.close().catch(()=>{}),i}}};0&&(module.exports={WarpMcp,buildZodInputSchema,convertActionToTool,convertMcpActionToTool,convertMcpArgsToWarpInputs,convertMcpToolToWarp,convertPromptActionToPrompt,convertWarpToMcpCapabilities,convertWarpsToMcpCapabilities,createAppResource,createMcpServerFromWarps,extractTextOrUndefined,interpolatePromptWithArgs});
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{getWarpPrimaryAction as S,WarpSerializer as v}from"@joai/warps";var W=(e,r)=>{let{action:n}=S(e);if(!n.inputs)return[];let t=new v;return n.inputs.map(i=>{let o=i.as||i.name,p=r[o]??i.default??null;return p===null&&i.type==="bool"?t.nativeToString(i.type,!1):t.nativeToString(i.type,p)})};import{WarpBuilder as $,getWarpPrimaryAction as j,resolveWarpText as _}from"@joai/warps";import{cleanWarpIdentifier as I}from"@joai/warps";import{z as m}from"zod";var z=e=>{if(e){if(Array.isArray(e))return e;if(typeof e=="object")return Object.keys(e)}},w=(e,r)=>{let n,t=e.type.toLowerCase();t==="string"||t==="address"||t==="hex"?n=m.string():t==="number"||t==="uint8"||t==="uint16"||t==="uint32"||t==="uint64"||t==="uint128"||t==="uint256"?n=m.number():t==="bool"||t==="boolean"?n=m.boolean():t==="biguint"?n=m.string():n=m.string(),typeof e.min=="number"&&n instanceof m.ZodNumber&&(n=n.min(e.min)),typeof e.max=="number"&&n instanceof m.ZodNumber&&(n=n.max(e.max)),e.pattern&&n instanceof m.ZodString&&(n=n.regex(new RegExp(e.pattern)));let i=z(e.options);if(i&&i.length>0){if(n instanceof m.ZodString)n=m.enum(i);else if(n instanceof m.ZodNumber){let u=i.map(a=>Number(a)).filter(a=>!isNaN(a));u.length>0&&(n=n.refine(a=>u.includes(a),{message:`Value must be one of: ${u.join(", ")}`}))}}let o=[],p=l(e.description,r);p&&o.push(p),e.bot&&o.push(e.bot),o.push(`Type: ${e.type}`),o.push(e.required?"Required":"Optional"),i&&i.length>0&&o.push(`Options: ${i.join(", ")}`);let s=l(e.patternDescription,r);s&&o.push(s);let c=o.join(". ");return c&&(n=n.describe(c)),e.required!==!0&&(n=n.optional()),n},y=(e,r)=>{let n={};for(let t of e){if(t.source==="hidden"||t.source!=="field")continue;let i=t.as||t.name;n[i]=w(t,r)}return Object.keys(n).length>0?n:void 0},T=(e,r,n,t,i,o)=>{let p=Z(e),s=t||r.inputs||[],c=y(s,o);return{name:p,description:n,inputSchema:c,meta:h(e,i,o)}},A=(e,r,n,t,i,o)=>{let p=t||r.inputs||[],s=y(p,o),c=r.destination?.tool;if(!c)throw new Error(`Tool name is required for MCP action ${r.type}`);return{name:c,description:n,inputSchema:s,meta:h(e,i,o)}},h=(e,r,n)=>{let t={"openai/widgetAccessible":!0};if(r&&(t["openai/outputTemplate"]=r.uri),e.messages){let i=l(e.messages.invoking,n),o=l(e.messages.invoked,n);i&&(t["openai/toolInvocation/invoking"]=i),o&&(t["openai/toolInvocation/invoked"]=o)}return t},Z=e=>{let r=e.meta?.identifier;if(!r)throw new Error(`Warp identifier for warp ${e.name} is required`);return I(r).replace(":",".")};import{WarpLogger as M}from"@joai/warps";var k=async e=>{if(e.startsWith("http://")||e.startsWith("https://")){let r=await fetch(e);if(!r.ok)throw new Error(`Failed to download component from ${e}: HTTP ${r.status} ${r.statusText}`);return r.text()}throw new Error(`Unsupported component path: ${e}`)},C=async(e,r,n)=>{if(!e.meta?.identifier)return null;try{let t=await k(r);return{name:e.name,uri:`ui://widget/${e.meta.identifier}`,description:`ChatGPT app for ${e.name}`,mimeType:"text/html+skybridge",content:t}}catch(t){let i=t instanceof Error?t.message:String(t),o=t instanceof Error?t.stack:void 0;return M.error(`[MCP] Failed to create app resource for warp "${e.name}" (path: ${r}):`,i),o&&M.error("[MCP] Error stack:",o),null}};var q=async(e,r)=>{let n=null,t=null,i=null;if(e.ui&&e.ui!=="table"&&(t=await C(e,e.ui,r)),e.actions.length===0)return{tool:null,resource:t,prompt:null};try{let{action:o}=j(e),p=l(e.description,r)||l(o.description,r);if(o.type==="prompt")i=x(e,o,p,r);else if(o.type==="mcp"){let s=o;s.destination&&(n=A(e,s,p,o.inputs,t,r))}else n=T(e,o,p,o.inputs,t,r)}catch{return{tool:null,resource:t,prompt:null}}return{tool:n,resource:t,prompt:i}},Se=async(e,r)=>Promise.all(e.map(n=>q(n,r))),E=(e,r)=>r==="date-time"||r==="date"||e==="string"?"string":e==="number"||e==="integer"?"uint256":e==="boolean"?"bool":"string",b=async(e,r,n,t)=>{let i=[];if(r.inputSchema?.properties){let s=r.inputSchema.properties,c=r.inputSchema.required||[];Object.entries(s).forEach(([u,a])=>{let d=c.includes(u),f=E(a.type||"string",a.format),g={name:u,label:typeof a.title=="string"?{en:a.title}:a.title||{en:u},description:a.description?{en:a.description.trim()}:null,type:f,position:`payload:${u}`,source:"field",required:d,...a.default!==void 0&&typeof a.default=="string"||typeof a.default=="number"||typeof a.default=="boolean"?{default:a.default}:{}};i.push(g)})}let o={};r.outputSchema?.properties&&Object.keys(r.outputSchema.properties).forEach(s=>{o[s]=`out.${s}`});let p={type:"mcp",label:{en:r.name},description:r.description?{en:r.description.trim()}:null,destination:{url:n,tool:r.name,headers:t},inputs:i};return await new $(e).setName(r.name||"unnamed_tool").setTitle({en:r.name||"Unnamed Tool"}).setDescription(r.description?{en:r.description.trim()}:null).addAction(p).setOutput(Object.keys(o).length>0?o:null).build(!1)},l=(e,r)=>e&&_(e,r)||void 0;var P=(e,r)=>{let n=e;for(let[t,i]of Object.entries(r)){let o=new RegExp(`\\{\\{\\s*${t}\\s*\\}\\}`,"g");n=n.replace(o,i??"")}return n},O=e=>(e.includes(":")?e.split(":").slice(1).join(":"):e).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,r=>r.includes("_")?"_":r).replace(/_+/g,"_"),N=(e,r)=>{let n=[];for(let t of e){if(t.source==="hidden"||t.source!=="field")continue;let i=t.as||t.name,o=l(t.description,r);n.push({name:i,description:o,required:t.required===!0})}return n},x=(e,r,n,t)=>{let i=O(e.name),o=r.inputs||[],p=N(o,t);return{name:i,description:n,arguments:p.length>0?p:void 0,prompt:r.prompt}};import{McpServer as U}from"@modelcontextprotocol/sdk/server/mcp.js";import{normalizeObjectSchema as D}from"@modelcontextprotocol/sdk/server/zod-compat.js";import{z as J}from"zod";var F=e=>{if(e)return typeof e=="object"&&"_zod"in e?e._zod:typeof e=="object"&&!Array.isArray(e)&&D(e)||e},L=e=>{if(!e.arguments||e.arguments.length===0)return;let r={};for(let n of e.arguments){let t=J.string();n.description&&(t=t.describe(n.description)),n.required||(t=t.optional()),r[n.name]=t}return r},_e=(e,r,n,t)=>{let i=new U({name:e.name,version:e.version||"1.0.0"});for(let o=0;o<n.length;o++){let{tool:p,resource:s,prompt:c}=n[o],u=r[o];if(p){let a=F(p.inputSchema),d={description:p.description||"",inputSchema:a,...p.meta&&{_meta:p.meta}};i.registerTool(p.name,d,async f=>{let g=W(u,f||{});return await t(u,g)})}if(s&&i.registerResource(s.name||s.uri,s.uri,{description:s.description,mimeType:s.mimeType},async()=>{let a={uri:s.uri,text:s.content||"",mimeType:s.mimeType};return s.meta&&(a._meta=s.meta),{contents:[a]}}),c){let a=L(c);i.registerPrompt(c.name,{description:c.description||"",argsSchema:a},d=>({messages:[{role:"user",content:{type:"text",text:P(c.prompt,d)}}]}))}}return i};import{Client as V}from"@modelcontextprotocol/sdk/client/index.js";import{StreamableHTTPClientTransport as H}from"@modelcontextprotocol/sdk/client/streamableHttp.js";var R=class{constructor(r){this.config=r}async getWarpsFromTools(r,n){let t=new H(new URL(r),{requestInit:{headers:n||{}}}),i=new V({name:"warps-mcp-client",version:"1.0.0"},{capabilities:{}});try{await i.connect(t);let o=await i.listTools();return await i.close(),await Promise.all(o.tools.map(p=>b(this.config,p,r,n)))}catch(o){throw await i.close().catch(()=>{}),o}}};export{R as WarpMcp,y as buildZodInputSchema,T as convertActionToTool,A as convertMcpActionToTool,W as convertMcpArgsToWarpInputs,b as convertMcpToolToWarp,x as convertPromptActionToPrompt,q as convertWarpToMcpCapabilities,Se as convertWarpsToMcpCapabilities,C as createAppResource,_e as createMcpServerFromWarps,l as extractTextOrUndefined,P as interpolatePromptWithArgs};
1
+ import{getWarpPrimaryAction as I,WarpSerializer as z}from"@joai/warps";var W=(e,r)=>{let{action:n}=I(e);if(!n.inputs)return[];let t=new z;return n.inputs.map(i=>{let o=i.as||i.name,s=r[o]??i.default??null;return s===null&&i.type==="bool"?t.nativeToString(i.type,!1):t.nativeToString(i.type,s)})};import{WarpBuilder as j,getWarpPrimaryAction as O,resolveWarpText as q}from"@joai/warps";import{cleanWarpIdentifier as w}from"@joai/warps";import{z as m}from"zod";var v=e=>{if(e){if(Array.isArray(e))return e;if(typeof e=="object")return Object.keys(e)}},Z=(e,r)=>{let n,t=e.type.toLowerCase();t==="string"||t==="address"||t==="hex"?n=m.string():t==="number"||t==="uint8"||t==="uint16"||t==="uint32"||t==="uint64"||t==="uint128"||t==="uint256"?n=m.number():t==="bool"||t==="boolean"?n=m.boolean():t==="biguint"?n=m.string():n=m.string(),typeof e.min=="number"&&n instanceof m.ZodNumber&&(n=n.min(e.min)),typeof e.max=="number"&&n instanceof m.ZodNumber&&(n=n.max(e.max)),e.pattern&&n instanceof m.ZodString&&(n=n.regex(new RegExp(e.pattern)));let i=v(e.options);if(i&&i.length>0){if(n instanceof m.ZodString)n=m.enum(i);else if(n instanceof m.ZodNumber){let u=i.map(a=>Number(a)).filter(a=>!isNaN(a));u.length>0&&(n=n.refine(a=>u.includes(a),{message:`Value must be one of: ${u.join(", ")}`}))}}let o=[],s=l(e.description,r);s&&o.push(s),e.bot&&o.push(e.bot),o.push(`Type: ${e.type}`),o.push(e.required?"Required":"Optional"),i&&i.length>0&&o.push(`Options: ${i.join(", ")}`);let p=l(e.patternDescription,r);p&&o.push(p);let c=o.join(". ");return c&&(n=n.describe(c)),e.required!==!0&&(n=n.optional()),n},y=(e,r)=>{let n={};for(let t of e){if(t.source==="hidden"||t.source!=="field")continue;let i=t.as||t.name;n[i]=Z(t,r)}return Object.keys(n).length>0?n:void 0},T=(e,r,n,t,i,o)=>{let s=_(e),p=t||r.inputs||[],c=y(p,o);return{name:s,description:n,inputSchema:c,meta:M(e,i,o)}},A=(e,r,n,t,i,o)=>{let s=t||r.inputs||[],p=y(s,o),c=r.destination?.tool;if(!c)throw new Error(`Tool name is required for MCP action ${r.type}`);return{name:c,description:n,inputSchema:p,meta:M(e,i,o)}},M=(e,r,n)=>{let t={visibility:["model","app"]};return r&&(t.resourceUri=r.uri),{ui:t}},_=e=>{let r=e.meta?.identifier;if(!r)throw new Error(`Warp identifier for warp ${e.name} is required`);return w(r).replace(":",".")};import{WarpLogger as h}from"@joai/warps";var E="text/html;profile=mcp-app",$=async e=>{if(e.startsWith("http://")||e.startsWith("https://")){let r=await fetch(e);if(!r.ok)throw new Error(`Failed to download component from ${e}: HTTP ${r.status} ${r.statusText}`);return r.text()}throw new Error(`Unsupported component path: ${e}`)},C=async(e,r,n)=>{if(!e.meta?.identifier)return null;try{let t=await $(r);return{name:e.name,uri:`ui://widget/${e.meta.identifier}`,description:`MCP app for ${e.name}`,mimeType:E,content:t}}catch(t){let i=t instanceof Error?t.message:String(t),o=t instanceof Error?t.stack:void 0;return h.error(`[MCP] Failed to create app resource for warp "${e.name}" (path: ${r}):`,i),o&&h.error("[MCP] Error stack:",o),null}};var k=async(e,r)=>{let n=null,t=null,i=null;if(e.ui&&e.ui!=="table"&&(t=await C(e,e.ui,r)),e.actions.length===0)return{tool:null,resource:t,prompt:null};try{let{action:o}=O(e),s=l(e.description,r)||l(o.description,r);if(o.type==="prompt")i=x(e,o,s,r);else if(o.type==="mcp"){let p=o;p.destination&&(n=A(e,p,s,o.inputs,t,r))}else n=T(e,o,s,o.inputs,t,r)}catch{return{tool:null,resource:t,prompt:null}}return{tool:n,resource:t,prompt:i}},ve=async(e,r)=>Promise.all(e.map(n=>k(n,r))),N=(e,r)=>r==="date-time"||r==="date"||e==="string"?"string":e==="number"||e==="integer"?"uint256":e==="boolean"?"bool":"string",b=async(e,r,n,t)=>{let i=[];if(r.inputSchema?.properties){let p=r.inputSchema.properties,c=r.inputSchema.required||[];Object.entries(p).forEach(([u,a])=>{let f=c.includes(u),d=N(a.type||"string",a.format),g={name:u,label:typeof a.title=="string"?{en:a.title}:a.title||{en:u},description:a.description?{en:a.description.trim()}:null,type:d,position:`payload:${u}`,source:"field",required:f,...a.default!==void 0&&typeof a.default=="string"||typeof a.default=="number"||typeof a.default=="boolean"?{default:a.default}:{}};i.push(g)})}let o={};r.outputSchema?.properties&&Object.keys(r.outputSchema.properties).forEach(p=>{o[p]=`out.${p}`});let s={type:"mcp",label:{en:r.name},description:r.description?{en:r.description.trim()}:null,destination:{url:n,tool:r.name,headers:t},inputs:i};return await new j(e).setName(r.name||"unnamed_tool").setTitle({en:r.name||"Unnamed Tool"}).setDescription(r.description?{en:r.description.trim()}:null).addAction(s).setOutput(Object.keys(o).length>0?o:null).build(!1)},l=(e,r)=>e&&q(e,r)||void 0;var P=(e,r)=>{let n=e;for(let[t,i]of Object.entries(r)){let o=new RegExp(`\\{\\{\\s*${t}\\s*\\}\\}`,"g");n=n.replace(o,i??"")}return n},U=e=>(e.includes(":")?e.split(":").slice(1).join(":"):e).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,r=>r.includes("_")?"_":r).replace(/_+/g,"_"),D=(e,r)=>{let n=[];for(let t of e){if(t.source==="hidden"||t.source!=="field")continue;let i=t.as||t.name,o=l(t.description,r);n.push({name:i,description:o,required:t.required===!0})}return n},x=(e,r,n,t)=>{let i=U(e.name),o=r.inputs||[],s=D(o,t);return{name:i,description:n,arguments:s.length>0?s:void 0,prompt:r.prompt}};import{McpServer as J}from"@modelcontextprotocol/sdk/server/mcp.js";import{normalizeObjectSchema as F}from"@modelcontextprotocol/sdk/server/zod-compat.js";import{registerAppTool as L,registerAppResource as V}from"@modelcontextprotocol/ext-apps/server";import{z as H}from"zod";var Q=e=>{if(e)return typeof e=="object"&&"_zod"in e?e._zod:typeof e=="object"&&!Array.isArray(e)&&F(e)||e},B=e=>{if(!e.arguments||e.arguments.length===0)return;let r={};for(let n of e.arguments){let t=H.string();n.description&&(t=t.describe(n.description)),n.required||(t=t.optional()),r[n.name]=t}return r},Ue=(e,r,n,t)=>{let i=new J({name:e.name,version:e.version||"1.0.0"});for(let o=0;o<n.length;o++){let{tool:s,resource:p,prompt:c}=n[o],u=r[o];if(s){let a=Q(s.inputSchema),f={description:s.description||"",inputSchema:a,...s.meta&&{_meta:s.meta}},d=async g=>{let S=W(u,g||{});return await t(u,S)};s.meta?.ui?.resourceUri?L(i,s.name,f,d):i.registerTool(s.name,f,d)}if(p&&(p.mimeType?.includes("profile=mcp-app")?V(i,p.name||p.uri,p.uri,{description:p.description},async()=>{let a={uri:p.uri,text:p.content||"",mimeType:p.mimeType};return p.meta&&(a._meta=p.meta),{contents:[a]}}):i.registerResource(p.name||p.uri,p.uri,{description:p.description,mimeType:p.mimeType},async()=>{let a={uri:p.uri,text:p.content||"",mimeType:p.mimeType};return p.meta&&(a._meta=p.meta),{contents:[a]}})),c){let a=B(c);i.registerPrompt(c.name,{description:c.description||"",argsSchema:a},f=>({messages:[{role:"user",content:{type:"text",text:P(c.prompt,f)}}]}))}}return i};import{Client as Y}from"@modelcontextprotocol/sdk/client/index.js";import{StreamableHTTPClientTransport as G}from"@modelcontextprotocol/sdk/client/streamableHttp.js";var R=class{constructor(r){this.config=r}async getWarpsFromTools(r,n){let t=new G(new URL(r),{requestInit:{headers:n||{}}}),i=new Y({name:"warps-mcp-client",version:"1.0.0"},{capabilities:{}});try{await i.connect(t);let o=await i.listTools();return await i.close(),await Promise.all(o.tools.map(s=>b(this.config,s,r,n)))}catch(o){throw await i.close().catch(()=>{}),o}}};export{R as WarpMcp,y as buildZodInputSchema,T as convertActionToTool,A as convertMcpActionToTool,W as convertMcpArgsToWarpInputs,b as convertMcpToolToWarp,x as convertPromptActionToPrompt,k as convertWarpToMcpCapabilities,ve as convertWarpsToMcpCapabilities,C as createAppResource,Ue as createMcpServerFromWarps,l as extractTextOrUndefined,P as interpolatePromptWithArgs};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joai/warps-mcp",
3
- "version": "1.0.0-beta.35",
3
+ "version": "1.0.0",
4
4
  "description": "MCP adapter for Warps SDK",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -26,6 +26,7 @@
26
26
  ],
27
27
  "devDependencies": {
28
28
  "@types/jest": "^30.0.0",
29
+ "@types/node": "^20.0.0",
29
30
  "jest": "^30.2.0",
30
31
  "jest-environment-jsdom": "^30.2.0",
31
32
  "jest-fetch-mock": "^3.0.3",
@@ -37,10 +38,11 @@
37
38
  "access": "public"
38
39
  },
39
40
  "dependencies": {
41
+ "@modelcontextprotocol/ext-apps": "^1.0.1",
40
42
  "@modelcontextprotocol/sdk": "^1.25.2",
41
43
  "zod": "^4.3.5"
42
44
  },
43
45
  "peerDependencies": {
44
- "@joai/warps": "^3.0.0-beta.200"
46
+ "@joai/warps": "^3.0.0"
45
47
  }
46
48
  }