@joai/warps-mcp 1.0.0-beta.27
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/README.md +61 -0
- package/dist/index.d.cts +95 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +2 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @joai/warps-mcp
|
|
2
|
+
|
|
3
|
+
Model Context Protocol (MCP) integration for the Warps SDK. Enables fetching and converting MCP tools into Warps.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @joai/warps-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
- `@joai/warps` core package
|
|
14
|
+
- `@modelcontextprotocol/sdk` (peer dependency)
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { WarpMcp } from '@joai/warps-mcp'
|
|
20
|
+
import { WarpClient } from '@joai/warps'
|
|
21
|
+
|
|
22
|
+
const config = {
|
|
23
|
+
env: 'mainnet',
|
|
24
|
+
// ... your config
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const mcp = new WarpMcp(config)
|
|
28
|
+
|
|
29
|
+
// Fetch Warps from an MCP server
|
|
30
|
+
const warps = await mcp.getWarpsFromTools('https://mcp-server.example.com', {
|
|
31
|
+
Authorization: 'Bearer token',
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// Use the Warps with WarpClient
|
|
35
|
+
const client = new WarpClient(config, { chains: [...] })
|
|
36
|
+
for (const warp of warps) {
|
|
37
|
+
await client.execute(warp, inputs)
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- Connect to MCP servers
|
|
44
|
+
- List available tools
|
|
45
|
+
- Convert MCP tools to Warps
|
|
46
|
+
- Execute Warps from MCP sources
|
|
47
|
+
|
|
48
|
+
## MCP Actions
|
|
49
|
+
|
|
50
|
+
Warps support `mcp` action types that can execute MCP tools directly:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
{
|
|
54
|
+
type: 'mcp',
|
|
55
|
+
destination: {
|
|
56
|
+
url: 'https://mcp-server.example.com',
|
|
57
|
+
tool: 'tool-name',
|
|
58
|
+
headers: { Authorization: 'Bearer token' }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Warp, WarpPromptAction, WarpClientConfig, WarpActionInput, WarpTransferAction, WarpContractAction, WarpCollectAction, WarpQueryAction, WarpMcpAction, WarpText } from '@joai/warps';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
+
|
|
5
|
+
declare const convertMcpArgsToWarpInputs: (warp: Warp, args: Record<string, any>) => string[];
|
|
6
|
+
|
|
7
|
+
type WarpMcpServerConfig = {
|
|
8
|
+
name: string;
|
|
9
|
+
version?: string;
|
|
10
|
+
executor?: WarpMcpExecutor;
|
|
11
|
+
};
|
|
12
|
+
type JsonSchema$1 = Record<string, unknown>;
|
|
13
|
+
type ToolInputSchema = Record<string, z.ZodTypeAny> | JsonSchema$1 | undefined;
|
|
14
|
+
type ToolOutputSchema = JsonSchema$1 | undefined;
|
|
15
|
+
type ToolMeta = Record<string, string | boolean>;
|
|
16
|
+
type ResourceMeta = Record<string, unknown>;
|
|
17
|
+
type WarpMcpTool = {
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
inputSchema?: ToolInputSchema;
|
|
21
|
+
outputSchema?: ToolOutputSchema;
|
|
22
|
+
meta?: ToolMeta;
|
|
23
|
+
};
|
|
24
|
+
type WarpMcpResource = {
|
|
25
|
+
name?: string;
|
|
26
|
+
uri: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
mimeType?: string;
|
|
29
|
+
content?: string;
|
|
30
|
+
meta?: ResourceMeta;
|
|
31
|
+
};
|
|
32
|
+
type WarpMcpPromptArgument = {
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
required?: boolean;
|
|
36
|
+
};
|
|
37
|
+
type WarpMcpPrompt = {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
arguments?: WarpMcpPromptArgument[];
|
|
41
|
+
prompt: string;
|
|
42
|
+
};
|
|
43
|
+
type WarpMcpCapabilities = {
|
|
44
|
+
tool?: WarpMcpTool | null;
|
|
45
|
+
resource?: WarpMcpResource | null;
|
|
46
|
+
prompt?: WarpMcpPrompt | null;
|
|
47
|
+
};
|
|
48
|
+
type McpToolArgs = Record<string, unknown>;
|
|
49
|
+
type McpToolResult = {
|
|
50
|
+
content: Array<{
|
|
51
|
+
type: 'text';
|
|
52
|
+
text: string;
|
|
53
|
+
}>;
|
|
54
|
+
};
|
|
55
|
+
type WarpMcpExecutor = (warp: Warp, inputs: string[]) => Promise<McpToolResult>;
|
|
56
|
+
|
|
57
|
+
declare const interpolatePromptWithArgs: (promptTemplate: string, args: Record<string, string>) => string;
|
|
58
|
+
declare const convertPromptActionToPrompt: (warp: Warp, action: WarpPromptAction, description: string | undefined, config: WarpClientConfig) => WarpMcpPrompt;
|
|
59
|
+
|
|
60
|
+
declare const buildZodInputSchema: (inputs: WarpActionInput[], config: WarpClientConfig) => Record<string, z.ZodTypeAny> | undefined;
|
|
61
|
+
declare const convertActionToTool: (warp: Warp, action: WarpTransferAction | WarpContractAction | WarpCollectAction | WarpQueryAction, description: string | undefined, primaryActionInputs: WarpActionInput[] | undefined, resource: WarpMcpResource | null, config: WarpClientConfig) => WarpMcpTool;
|
|
62
|
+
declare const convertMcpActionToTool: (warp: Warp, action: WarpMcpAction, description: string | undefined, primaryActionInputs: WarpActionInput[] | undefined, resource: WarpMcpResource | null, config: WarpClientConfig) => WarpMcpTool;
|
|
63
|
+
|
|
64
|
+
declare const createAppResource: (warp: Warp, appUrl: string, config: WarpClientConfig) => Promise<WarpMcpResource | null>;
|
|
65
|
+
|
|
66
|
+
declare const convertWarpToMcpCapabilities: (warp: Warp, config: WarpClientConfig) => Promise<WarpMcpCapabilities>;
|
|
67
|
+
declare const convertWarpsToMcpCapabilities: (warps: Warp[], config: WarpClientConfig) => Promise<WarpMcpCapabilities[]>;
|
|
68
|
+
type JsonSchemaProperty = {
|
|
69
|
+
type?: string;
|
|
70
|
+
format?: string;
|
|
71
|
+
title?: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
default?: unknown;
|
|
74
|
+
};
|
|
75
|
+
type JsonSchema = {
|
|
76
|
+
properties?: Record<string, JsonSchemaProperty>;
|
|
77
|
+
required?: string[];
|
|
78
|
+
};
|
|
79
|
+
declare const convertMcpToolToWarp: (config: WarpClientConfig, tool: {
|
|
80
|
+
name: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
inputSchema?: JsonSchema;
|
|
83
|
+
outputSchema?: JsonSchema;
|
|
84
|
+
}, url: string, headers?: Record<string, string>) => Promise<Warp>;
|
|
85
|
+
declare const extractTextOrUndefined: (text: WarpText | null | undefined, config: WarpClientConfig) => string | undefined;
|
|
86
|
+
|
|
87
|
+
declare const createMcpServerFromWarps: (config: WarpMcpServerConfig, warps: Warp[], capabilities: WarpMcpCapabilities[], executor?: WarpMcpExecutor) => McpServer;
|
|
88
|
+
|
|
89
|
+
declare class WarpMcp {
|
|
90
|
+
private readonly config;
|
|
91
|
+
constructor(config: WarpClientConfig);
|
|
92
|
+
getWarpsFromTools(url: string, headers?: Record<string, string>): Promise<Warp[]>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { type JsonSchema$1 as JsonSchema, type McpToolArgs, type McpToolResult, type ResourceMeta, type ToolInputSchema, type ToolMeta, type ToolOutputSchema, WarpMcp, type WarpMcpCapabilities, type WarpMcpExecutor, type WarpMcpPrompt, type WarpMcpPromptArgument, type WarpMcpResource, type WarpMcpServerConfig, type WarpMcpTool, buildZodInputSchema, convertActionToTool, convertMcpActionToTool, convertMcpArgsToWarpInputs, convertMcpToolToWarp, convertPromptActionToPrompt, convertWarpToMcpCapabilities, convertWarpsToMcpCapabilities, createAppResource, createMcpServerFromWarps, extractTextOrUndefined, interpolatePromptWithArgs };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Warp, WarpPromptAction, WarpClientConfig, WarpActionInput, WarpTransferAction, WarpContractAction, WarpCollectAction, WarpQueryAction, WarpMcpAction, WarpText } from '@joai/warps';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
+
|
|
5
|
+
declare const convertMcpArgsToWarpInputs: (warp: Warp, args: Record<string, any>) => string[];
|
|
6
|
+
|
|
7
|
+
type WarpMcpServerConfig = {
|
|
8
|
+
name: string;
|
|
9
|
+
version?: string;
|
|
10
|
+
executor?: WarpMcpExecutor;
|
|
11
|
+
};
|
|
12
|
+
type JsonSchema$1 = Record<string, unknown>;
|
|
13
|
+
type ToolInputSchema = Record<string, z.ZodTypeAny> | JsonSchema$1 | undefined;
|
|
14
|
+
type ToolOutputSchema = JsonSchema$1 | undefined;
|
|
15
|
+
type ToolMeta = Record<string, string | boolean>;
|
|
16
|
+
type ResourceMeta = Record<string, unknown>;
|
|
17
|
+
type WarpMcpTool = {
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
inputSchema?: ToolInputSchema;
|
|
21
|
+
outputSchema?: ToolOutputSchema;
|
|
22
|
+
meta?: ToolMeta;
|
|
23
|
+
};
|
|
24
|
+
type WarpMcpResource = {
|
|
25
|
+
name?: string;
|
|
26
|
+
uri: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
mimeType?: string;
|
|
29
|
+
content?: string;
|
|
30
|
+
meta?: ResourceMeta;
|
|
31
|
+
};
|
|
32
|
+
type WarpMcpPromptArgument = {
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
required?: boolean;
|
|
36
|
+
};
|
|
37
|
+
type WarpMcpPrompt = {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
arguments?: WarpMcpPromptArgument[];
|
|
41
|
+
prompt: string;
|
|
42
|
+
};
|
|
43
|
+
type WarpMcpCapabilities = {
|
|
44
|
+
tool?: WarpMcpTool | null;
|
|
45
|
+
resource?: WarpMcpResource | null;
|
|
46
|
+
prompt?: WarpMcpPrompt | null;
|
|
47
|
+
};
|
|
48
|
+
type McpToolArgs = Record<string, unknown>;
|
|
49
|
+
type McpToolResult = {
|
|
50
|
+
content: Array<{
|
|
51
|
+
type: 'text';
|
|
52
|
+
text: string;
|
|
53
|
+
}>;
|
|
54
|
+
};
|
|
55
|
+
type WarpMcpExecutor = (warp: Warp, inputs: string[]) => Promise<McpToolResult>;
|
|
56
|
+
|
|
57
|
+
declare const interpolatePromptWithArgs: (promptTemplate: string, args: Record<string, string>) => string;
|
|
58
|
+
declare const convertPromptActionToPrompt: (warp: Warp, action: WarpPromptAction, description: string | undefined, config: WarpClientConfig) => WarpMcpPrompt;
|
|
59
|
+
|
|
60
|
+
declare const buildZodInputSchema: (inputs: WarpActionInput[], config: WarpClientConfig) => Record<string, z.ZodTypeAny> | undefined;
|
|
61
|
+
declare const convertActionToTool: (warp: Warp, action: WarpTransferAction | WarpContractAction | WarpCollectAction | WarpQueryAction, description: string | undefined, primaryActionInputs: WarpActionInput[] | undefined, resource: WarpMcpResource | null, config: WarpClientConfig) => WarpMcpTool;
|
|
62
|
+
declare const convertMcpActionToTool: (warp: Warp, action: WarpMcpAction, description: string | undefined, primaryActionInputs: WarpActionInput[] | undefined, resource: WarpMcpResource | null, config: WarpClientConfig) => WarpMcpTool;
|
|
63
|
+
|
|
64
|
+
declare const createAppResource: (warp: Warp, appUrl: string, config: WarpClientConfig) => Promise<WarpMcpResource | null>;
|
|
65
|
+
|
|
66
|
+
declare const convertWarpToMcpCapabilities: (warp: Warp, config: WarpClientConfig) => Promise<WarpMcpCapabilities>;
|
|
67
|
+
declare const convertWarpsToMcpCapabilities: (warps: Warp[], config: WarpClientConfig) => Promise<WarpMcpCapabilities[]>;
|
|
68
|
+
type JsonSchemaProperty = {
|
|
69
|
+
type?: string;
|
|
70
|
+
format?: string;
|
|
71
|
+
title?: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
default?: unknown;
|
|
74
|
+
};
|
|
75
|
+
type JsonSchema = {
|
|
76
|
+
properties?: Record<string, JsonSchemaProperty>;
|
|
77
|
+
required?: string[];
|
|
78
|
+
};
|
|
79
|
+
declare const convertMcpToolToWarp: (config: WarpClientConfig, tool: {
|
|
80
|
+
name: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
inputSchema?: JsonSchema;
|
|
83
|
+
outputSchema?: JsonSchema;
|
|
84
|
+
}, url: string, headers?: Record<string, string>) => Promise<Warp>;
|
|
85
|
+
declare const extractTextOrUndefined: (text: WarpText | null | undefined, config: WarpClientConfig) => string | undefined;
|
|
86
|
+
|
|
87
|
+
declare const createMcpServerFromWarps: (config: WarpMcpServerConfig, warps: Warp[], capabilities: WarpMcpCapabilities[], executor?: WarpMcpExecutor) => McpServer;
|
|
88
|
+
|
|
89
|
+
declare class WarpMcp {
|
|
90
|
+
private readonly config;
|
|
91
|
+
constructor(config: WarpClientConfig);
|
|
92
|
+
getWarpsFromTools(url: string, headers?: Record<string, string>): Promise<Warp[]>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { type JsonSchema$1 as JsonSchema, type McpToolArgs, type McpToolResult, type ResourceMeta, type ToolInputSchema, type ToolMeta, type ToolOutputSchema, WarpMcp, type WarpMcpCapabilities, type WarpMcpExecutor, type WarpMcpPrompt, type WarpMcpPromptArgument, type WarpMcpResource, type WarpMcpServerConfig, type WarpMcpTool, buildZodInputSchema, convertActionToTool, convertMcpActionToTool, convertMcpArgsToWarpInputs, convertMcpToolToWarp, convertPromptActionToPrompt, convertWarpToMcpCapabilities, convertWarpsToMcpCapabilities, createAppResource, createMcpServerFromWarps, extractTextOrUndefined, interpolatePromptWithArgs };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var h=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var D=(t,e)=>{for(var r in e)h(t,r,{get:e[r],enumerable:!0})},L=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of J(e))!U.call(t,o)&&o!==r&&h(t,o,{get:()=>e[o],enumerable:!(n=q(e,o))||n.enumerable});return t};var F=t=>L(h({},"__esModule",{value:!0}),t);var it={};D(it,{WarpMcp:()=>z,buildZodInputSchema:()=>M,convertActionToTool:()=>b,convertMcpActionToTool:()=>C,convertMcpArgsToWarpInputs:()=>A,convertMcpToolToWarp:()=>R,convertPromptActionToPrompt:()=>S,convertWarpToMcpCapabilities:()=>$,convertWarpsToMcpCapabilities:()=>X,createAppResource:()=>P,createMcpServerFromWarps:()=>ot,extractTextOrUndefined:()=>u,interpolatePromptWithArgs:()=>v});module.exports=F(it);var T=require("@joai/warps"),A=(t,e)=>{let{action:r}=(0,T.getWarpPrimaryAction)(t);if(!r.inputs)return[];let n=new T.WarpSerializer;return r.inputs.map(o=>{let i=o.as||o.name,a=e[i]??o.default??null;return a===null&&o.type==="bool"?n.nativeToString(o.type,!1):n.nativeToString(o.type,a)})};var f=require("@joai/warps");var W=require("@joai/warps"),m=require("zod");var V=t=>{if(t){if(Array.isArray(t))return t;if(typeof t=="object")return Object.keys(t)}},I=t=>(t.includes(":")?t.split(":").slice(1).join(":"):t).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,e=>e.includes("_")?"_":e).replace(/_+/g,"_"),H=(t,e)=>{let r,n=t.type.toLowerCase();n==="string"||n==="address"||n==="hex"?r=m.z.string():n==="number"||n==="uint8"||n==="uint16"||n==="uint32"||n==="uint64"||n==="uint128"||n==="uint256"?r=m.z.number():n==="bool"||n==="boolean"?r=m.z.boolean():n==="biguint"?r=m.z.string():r=m.z.string(),typeof t.min=="number"&&r instanceof m.z.ZodNumber&&(r=r.min(t.min)),typeof t.max=="number"&&r instanceof m.z.ZodNumber&&(r=r.max(t.max)),t.pattern&&r instanceof m.z.ZodString&&(r=r.regex(new RegExp(t.pattern)));let o=V(t.options);if(o&&o.length>0){if(r instanceof m.z.ZodString)r=m.z.enum(o);else if(r instanceof m.z.ZodNumber){let l=o.map(s=>Number(s)).filter(s=>!isNaN(s));l.length>0&&(r=r.refine(s=>l.includes(s),{message:`Value must be one of: ${l.join(", ")}`}))}}let i=[],a=u(t.description,e);a&&i.push(a),t.bot&&i.push(t.bot),i.push(`Type: ${t.type}`),i.push(t.required?"Required":"Optional"),o&&o.length>0&&i.push(`Options: ${o.join(", ")}`);let c=u(t.patternDescription,e);c&&i.push(c);let p=i.join(". ");return p&&(r=r.describe(p)),t.required!==!0&&(r=r.optional()),r},M=(t,e)=>{let r={};for(let n of t){if(n.source==="hidden"||n.source!=="field")continue;let o=n.as||n.name;r[o]=H(n,e)}return W.WarpLogger.info("[MCP] buildZodInputSchema - inputs:",t.length,"shape keys:",Object.keys(r)),Object.keys(r).length>0?r:void 0},b=(t,e,r,n,o,i)=>{let a=n||e.inputs||[],c=M(a,i),p=I(t.name);W.WarpLogger.info(`[MCP] convertActionToTool - tool: ${p}, inputsToUse: ${a.length}, inputSchema keys:`,c?Object.keys(c):"undefined");let l={name:p,description:r,inputSchema:c,meta:k(t,o,i)};return W.WarpLogger.info(`[MCP] convertActionToTool - tool: ${p}, meta:`,JSON.stringify(l.meta,null,2)),l},C=(t,e,r,n,o,i)=>{let a=n||e.inputs||[],c=M(a,i),p=e.destination.tool,l=I(p),s={name:l,description:r,inputSchema:c,meta:k(t,o,i)};return W.WarpLogger.info(`[MCP] convertMcpActionToTool - tool: ${l}, meta:`,JSON.stringify(s.meta,null,2)),s},k=(t,e,r)=>{let n={"openai/widgetAccessible":!0};if(e&&(n["openai/outputTemplate"]=e.uri),t.messages){let o=u(t.messages.invoking,r),i=u(t.messages.invoked,r);o&&(n["openai/toolInvocation/invoking"]=o),i&&(n["openai/toolInvocation/invoked"]=i)}return n};var x=require("@joai/warps");var Q=async t=>{let e=await fetch(t);if(!e.ok)throw new Error(`Failed to download app from ${t}: HTTP ${e.status} ${e.statusText}`);return e.text()},_=(t,e)=>{if(e.startsWith("http://")||e.startsWith("https://"))return e;let r=new URL(t);return new URL(e,r).href},B=async(t,e)=>{let r=/<link[^>]+rel=["']stylesheet["'][^>]+href=["']([^"']+)["'][^>]*>/gi,n=/<script[^>]+src=["']([^"']+)["'][^>]*><\/script>/gi,o=[],i;for(;(i=r.exec(t))!==null;){let p=i[0],l=_(e,i[1]);o.push(fetch(l).then(s=>s.ok?s.text():"").then(s=>({match:p,content:s?`<style>${s}</style>`:""})).catch(()=>({match:p,content:""})))}for(;(i=n.exec(t))!==null;){let p=i[0],l=_(e,i[1]);o.push(fetch(l).then(s=>s.ok?s.text():"").then(s=>({match:p,content:s?`<script>${s}</script>`:""})).catch(()=>({match:p,content:""})))}if(o.length===0)return t;let a=await Promise.all(o),c=t;for(let{match:p,content:l}of a)c=c.replace(p,l||"");return c},G=t=>{let e=t;return e=e.replace(/<html[^>]*>/gi,"").replace(/<\/html>/gi,""),e=e.replace(/<head[^>]*>/gi,"").replace(/<\/head>/gi,""),e=e.replace(/<body[^>]*>/gi,"").replace(/<\/body>/gi,""),e.trim()},K=(t,e)=>{let r=`<script type="application/json" id="warp-app-data">${JSON.stringify(e)}</script>`,n=G(t);return`${r}
|
|
2
|
+
${n}`},P=async(t,e,r)=>{if(!t.meta?.identifier)return null;try{let n=await Q(e);n=await B(n,e);let o={warp:{name:t.name,title:u(t.title,r),description:u(t.description,r)}};return{name:t.name,uri:`ui://widget/${t.meta.identifier}`,description:`ChatGPT app for ${t.name}`,mimeType:"text/html+skybridge",content:K(n,o)}}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 "${t.name}" (url: ${e}):`,o),i&&x.WarpLogger.error("[MCP] Error stack:",i),null}};var $=async(t,e)=>{let r=null,n=null,o=null;if(t.ui&&t.ui!=="table"&&(n=await P(t,t.ui,e)),t.actions.length===0)return{tool:null,resource:n,prompt:null};try{let{action:i}=(0,f.getWarpPrimaryAction)(t),a=u(t.description,e)||u(i.description,e);if(i.type==="prompt")o=S(t,i,a,e);else if(i.type==="mcp"){let c=i;c.destination&&(r=C(t,c,a,i.inputs,n,e))}else r=b(t,i,a,i.inputs,n,e)}catch{return{tool:null,resource:n,prompt:null}}return{tool:r,resource:n,prompt:o}},X=async(t,e)=>Promise.all(t.map(r=>$(r,e))),Y=(t,e)=>e==="date-time"||e==="date"||t==="string"?"string":t==="number"||t==="integer"?"uint256":t==="boolean"?"bool":"string",R=async(t,e,r,n)=>{let o=[];if(e.inputSchema?.properties){let c=e.inputSchema.properties,p=e.inputSchema.required||[];Object.entries(c).forEach(([l,s])=>{let d=p.includes(l),g=Y(s.type||"string",s.format),y={name:l,label:typeof s.title=="string"?{en:s.title}:s.title||{en:l},description:s.description?{en:s.description.trim()}:null,type:g,position:`payload:${l}`,source:"field",required:d,...s.default!==void 0&&typeof s.default=="string"||typeof s.default=="number"||typeof s.default=="boolean"?{default:s.default}:{}};o.push(y)})}let i={};e.outputSchema?.properties&&Object.keys(e.outputSchema.properties).forEach(c=>{i[c]=`out.${c}`});let a={type:"mcp",label:{en:e.name},description:e.description?{en:e.description.trim()}:null,destination:{url:r,tool:e.name,headers:n},inputs:o};return await new f.WarpBuilder(t).setName(e.name||"unnamed_tool").setTitle({en:e.name||"Unnamed Tool"}).setDescription(e.description?{en:e.description.trim()}:null).addAction(a).setOutput(Object.keys(i).length>0?i:null).build(!1)},u=(t,e)=>t&&(0,f.resolveWarpText)(t,e)||void 0;var v=(t,e)=>{let r=t;for(let[n,o]of Object.entries(e)){let i=new RegExp(`\\{\\{\\s*${n}\\s*\\}\\}`,"g");r=r.replace(i,o??"")}return r},tt=t=>(t.includes(":")?t.split(":").slice(1).join(":"):t).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,e=>e.includes("_")?"_":e).replace(/_+/g,"_"),et=(t,e)=>{let r=[];for(let n of t){if(n.source==="hidden"||n.source!=="field")continue;let o=n.as||n.name,i=u(n.description,e);r.push({name:o,description:i,required:n.required===!0})}return r},S=(t,e,r,n)=>{let o=tt(t.name),i=e.inputs||[],a=et(i,n);return{name:o,description:r,arguments:a.length>0?a:void 0,prompt:e.prompt}};var w=require("@modelcontextprotocol/sdk/server/mcp.js"),j=require("@modelcontextprotocol/sdk/server/zod-compat.js"),Z=require("zod");var rt=t=>{if(t)return typeof t=="object"&&"_zod"in t?t._zod:typeof t=="object"&&!Array.isArray(t)&&(0,j.normalizeObjectSchema)(t)||t},nt=t=>{if(!t.arguments||t.arguments.length===0)return;let e={};for(let r of t.arguments){let n=Z.z.string();r.description&&(n=n.describe(r.description)),r.required||(n=n.optional()),e[r.name]=n}return e},ot=(t,e,r,n)=>{let o=new w.McpServer({name:t.name,version:t.version||"1.0.0"}),i=t.executor||n;for(let a=0;a<r.length;a++){let{tool:c,resource:p,prompt:l}=r[a],s=e[a];if(c){let d=rt(c.inputSchema),g={description:c.description||"",inputSchema:d,...c.meta&&{_meta:c.meta}};o.registerTool(c.name,g,async y=>{if(i){let E=A(s,y||{});return await i(s,E)}return{content:[{type:"text",text:`Tool ${c.name} executed successfully`}]}})}if(p&&o.registerResource(p.name||p.uri,p.uri,{description:p.description,mimeType:p.mimeType},async()=>{let d={uri:p.uri,text:p.content||"",mimeType:p.mimeType};return p.meta&&(d._meta=p.meta),{contents:[d]}}),l){let d=nt(l);o.registerPrompt(l.name,{description:l.description||"",argsSchema:d},g=>({messages:[{role:"user",content:{type:"text",text:v(l.prompt,g)}}]}))}}return o};var O=require("@modelcontextprotocol/sdk/client/index.js"),N=require("@modelcontextprotocol/sdk/client/streamableHttp.js");var z=class{constructor(e){this.config=e}async getWarpsFromTools(e,r){let n=new N.StreamableHTTPClientTransport(new URL(e),{requestInit:{headers:r||{}}}),o=new O.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(a=>R(this.config,a,e,r)))}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
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{getWarpPrimaryAction as k,WarpSerializer as _}from"@joai/warps";var y=(t,e)=>{let{action:r}=k(t);if(!r.inputs)return[];let n=new _;return r.inputs.map(i=>{let o=i.as||i.name,a=e[o]??i.default??null;return a===null&&i.type==="bool"?n.nativeToString(i.type,!1):n.nativeToString(i.type,a)})};import{WarpBuilder as E,getWarpPrimaryAction as q,resolveWarpText as J}from"@joai/warps";import{WarpLogger as W}from"@joai/warps";import{z as m}from"zod";var $=t=>{if(t){if(Array.isArray(t))return t;if(typeof t=="object")return Object.keys(t)}},T=t=>(t.includes(":")?t.split(":").slice(1).join(":"):t).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,e=>e.includes("_")?"_":e).replace(/_+/g,"_"),w=(t,e)=>{let r,n=t.type.toLowerCase();n==="string"||n==="address"||n==="hex"?r=m.string():n==="number"||n==="uint8"||n==="uint16"||n==="uint32"||n==="uint64"||n==="uint128"||n==="uint256"?r=m.number():n==="bool"||n==="boolean"?r=m.boolean():n==="biguint"?r=m.string():r=m.string(),typeof t.min=="number"&&r instanceof m.ZodNumber&&(r=r.min(t.min)),typeof t.max=="number"&&r instanceof m.ZodNumber&&(r=r.max(t.max)),t.pattern&&r instanceof m.ZodString&&(r=r.regex(new RegExp(t.pattern)));let i=$(t.options);if(i&&i.length>0){if(r instanceof m.ZodString)r=m.enum(i);else if(r instanceof m.ZodNumber){let l=i.map(s=>Number(s)).filter(s=>!isNaN(s));l.length>0&&(r=r.refine(s=>l.includes(s),{message:`Value must be one of: ${l.join(", ")}`}))}}let o=[],a=u(t.description,e);a&&o.push(a),t.bot&&o.push(t.bot),o.push(`Type: ${t.type}`),o.push(t.required?"Required":"Optional"),i&&i.length>0&&o.push(`Options: ${i.join(", ")}`);let c=u(t.patternDescription,e);c&&o.push(c);let p=o.join(". ");return p&&(r=r.describe(p)),t.required!==!0&&(r=r.optional()),r},h=(t,e)=>{let r={};for(let n of t){if(n.source==="hidden"||n.source!=="field")continue;let i=n.as||n.name;r[i]=w(n,e)}return W.info("[MCP] buildZodInputSchema - inputs:",t.length,"shape keys:",Object.keys(r)),Object.keys(r).length>0?r:void 0},A=(t,e,r,n,i,o)=>{let a=n||e.inputs||[],c=h(a,o),p=T(t.name);W.info(`[MCP] convertActionToTool - tool: ${p}, inputsToUse: ${a.length}, inputSchema keys:`,c?Object.keys(c):"undefined");let l={name:p,description:r,inputSchema:c,meta:b(t,i,o)};return W.info(`[MCP] convertActionToTool - tool: ${p}, meta:`,JSON.stringify(l.meta,null,2)),l},M=(t,e,r,n,i,o)=>{let a=n||e.inputs||[],c=h(a,o),p=e.destination.tool,l=T(p),s={name:l,description:r,inputSchema:c,meta:b(t,i,o)};return W.info(`[MCP] convertMcpActionToTool - tool: ${l}, meta:`,JSON.stringify(s.meta,null,2)),s},b=(t,e,r)=>{let n={"openai/widgetAccessible":!0};if(e&&(n["openai/outputTemplate"]=e.uri),t.messages){let i=u(t.messages.invoking,r),o=u(t.messages.invoked,r);i&&(n["openai/toolInvocation/invoking"]=i),o&&(n["openai/toolInvocation/invoked"]=o)}return n};import{WarpLogger as C}from"@joai/warps";var j=async t=>{let e=await fetch(t);if(!e.ok)throw new Error(`Failed to download app from ${t}: HTTP ${e.status} ${e.statusText}`);return e.text()},x=(t,e)=>{if(e.startsWith("http://")||e.startsWith("https://"))return e;let r=new URL(t);return new URL(e,r).href},Z=async(t,e)=>{let r=/<link[^>]+rel=["']stylesheet["'][^>]+href=["']([^"']+)["'][^>]*>/gi,n=/<script[^>]+src=["']([^"']+)["'][^>]*><\/script>/gi,i=[],o;for(;(o=r.exec(t))!==null;){let p=o[0],l=x(e,o[1]);i.push(fetch(l).then(s=>s.ok?s.text():"").then(s=>({match:p,content:s?`<style>${s}</style>`:""})).catch(()=>({match:p,content:""})))}for(;(o=n.exec(t))!==null;){let p=o[0],l=x(e,o[1]);i.push(fetch(l).then(s=>s.ok?s.text():"").then(s=>({match:p,content:s?`<script>${s}</script>`:""})).catch(()=>({match:p,content:""})))}if(i.length===0)return t;let a=await Promise.all(i),c=t;for(let{match:p,content:l}of a)c=c.replace(p,l||"");return c},O=t=>{let e=t;return e=e.replace(/<html[^>]*>/gi,"").replace(/<\/html>/gi,""),e=e.replace(/<head[^>]*>/gi,"").replace(/<\/head>/gi,""),e=e.replace(/<body[^>]*>/gi,"").replace(/<\/body>/gi,""),e.trim()},N=(t,e)=>{let r=`<script type="application/json" id="warp-app-data">${JSON.stringify(e)}</script>`,n=O(t);return`${r}
|
|
2
|
+
${n}`},P=async(t,e,r)=>{if(!t.meta?.identifier)return null;try{let n=await j(e);n=await Z(n,e);let i={warp:{name:t.name,title:u(t.title,r),description:u(t.description,r)}};return{name:t.name,uri:`ui://widget/${t.meta.identifier}`,description:`ChatGPT app for ${t.name}`,mimeType:"text/html+skybridge",content:N(n,i)}}catch(n){let i=n instanceof Error?n.message:String(n),o=n instanceof Error?n.stack:void 0;return C.error(`[MCP] Failed to create app resource for warp "${t.name}" (url: ${e}):`,i),o&&C.error("[MCP] Error stack:",o),null}};var U=async(t,e)=>{let r=null,n=null,i=null;if(t.ui&&t.ui!=="table"&&(n=await P(t,t.ui,e)),t.actions.length===0)return{tool:null,resource:n,prompt:null};try{let{action:o}=q(t),a=u(t.description,e)||u(o.description,e);if(o.type==="prompt")i=S(t,o,a,e);else if(o.type==="mcp"){let c=o;c.destination&&(r=M(t,c,a,o.inputs,n,e))}else r=A(t,o,a,o.inputs,n,e)}catch{return{tool:null,resource:n,prompt:null}}return{tool:r,resource:n,prompt:i}},$t=async(t,e)=>Promise.all(t.map(r=>U(r,e))),D=(t,e)=>e==="date-time"||e==="date"||t==="string"?"string":t==="number"||t==="integer"?"uint256":t==="boolean"?"bool":"string",R=async(t,e,r,n)=>{let i=[];if(e.inputSchema?.properties){let c=e.inputSchema.properties,p=e.inputSchema.required||[];Object.entries(c).forEach(([l,s])=>{let d=p.includes(l),f=D(s.type||"string",s.format),g={name:l,label:typeof s.title=="string"?{en:s.title}:s.title||{en:l},description:s.description?{en:s.description.trim()}:null,type:f,position:`payload:${l}`,source:"field",required:d,...s.default!==void 0&&typeof s.default=="string"||typeof s.default=="number"||typeof s.default=="boolean"?{default:s.default}:{}};i.push(g)})}let o={};e.outputSchema?.properties&&Object.keys(e.outputSchema.properties).forEach(c=>{o[c]=`out.${c}`});let a={type:"mcp",label:{en:e.name},description:e.description?{en:e.description.trim()}:null,destination:{url:r,tool:e.name,headers:n},inputs:i};return await new E(t).setName(e.name||"unnamed_tool").setTitle({en:e.name||"Unnamed Tool"}).setDescription(e.description?{en:e.description.trim()}:null).addAction(a).setOutput(Object.keys(o).length>0?o:null).build(!1)},u=(t,e)=>t&&J(t,e)||void 0;var v=(t,e)=>{let r=t;for(let[n,i]of Object.entries(e)){let o=new RegExp(`\\{\\{\\s*${n}\\s*\\}\\}`,"g");r=r.replace(o,i??"")}return r},L=t=>(t.includes(":")?t.split(":").slice(1).join(":"):t).trim().toLowerCase().replace(/\s+/g,"_").replace(/:/g,"_").replace(/[^a-z0-9_.-]/g,"_").replace(/^[^a-z0-9]+|[^a-z0-9]+$/g,"").replace(/[_-]+/g,e=>e.includes("_")?"_":e).replace(/_+/g,"_"),F=(t,e)=>{let r=[];for(let n of t){if(n.source==="hidden"||n.source!=="field")continue;let i=n.as||n.name,o=u(n.description,e);r.push({name:i,description:o,required:n.required===!0})}return r},S=(t,e,r,n)=>{let i=L(t.name),o=e.inputs||[],a=F(o,n);return{name:i,description:r,arguments:a.length>0?a:void 0,prompt:e.prompt}};import{McpServer as V}from"@modelcontextprotocol/sdk/server/mcp.js";import{normalizeObjectSchema as H}from"@modelcontextprotocol/sdk/server/zod-compat.js";import{z as Q}from"zod";var B=t=>{if(t)return typeof t=="object"&&"_zod"in t?t._zod:typeof t=="object"&&!Array.isArray(t)&&H(t)||t},G=t=>{if(!t.arguments||t.arguments.length===0)return;let e={};for(let r of t.arguments){let n=Q.string();r.description&&(n=n.describe(r.description)),r.required||(n=n.optional()),e[r.name]=n}return e},Ut=(t,e,r,n)=>{let i=new V({name:t.name,version:t.version||"1.0.0"}),o=t.executor||n;for(let a=0;a<r.length;a++){let{tool:c,resource:p,prompt:l}=r[a],s=e[a];if(c){let d=B(c.inputSchema),f={description:c.description||"",inputSchema:d,...c.meta&&{_meta:c.meta}};i.registerTool(c.name,f,async g=>{if(o){let I=y(s,g||{});return await o(s,I)}return{content:[{type:"text",text:`Tool ${c.name} executed successfully`}]}})}if(p&&i.registerResource(p.name||p.uri,p.uri,{description:p.description,mimeType:p.mimeType},async()=>{let d={uri:p.uri,text:p.content||"",mimeType:p.mimeType};return p.meta&&(d._meta=p.meta),{contents:[d]}}),l){let d=G(l);i.registerPrompt(l.name,{description:l.description||"",argsSchema:d},f=>({messages:[{role:"user",content:{type:"text",text:v(l.prompt,f)}}]}))}}return i};import{Client as K}from"@modelcontextprotocol/sdk/client/index.js";import{StreamableHTTPClientTransport as X}from"@modelcontextprotocol/sdk/client/streamableHttp.js";var z=class{constructor(e){this.config=e}async getWarpsFromTools(e,r){let n=new X(new URL(e),{requestInit:{headers:r||{}}}),i=new K({name:"warps-mcp-client",version:"1.0.0"},{capabilities:{}});try{await i.connect(n);let o=await i.listTools();return await i.close(),await Promise.all(o.tools.map(a=>R(this.config,a,e,r)))}catch(o){throw await i.close().catch(()=>{}),o}}};export{z as WarpMcp,h as buildZodInputSchema,A as convertActionToTool,M as convertMcpActionToTool,y as convertMcpArgsToWarpInputs,R as convertMcpToolToWarp,S as convertPromptActionToPrompt,U as convertWarpToMcpCapabilities,$t as convertWarpsToMcpCapabilities,P as createAppResource,Ut as createMcpServerFromWarps,u as extractTextOrUndefined,v as interpolatePromptWithArgs};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@joai/warps-mcp",
|
|
3
|
+
"version": "1.0.0-beta.27",
|
|
4
|
+
"description": "MCP adapter for Warps SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.mjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"test": "jest --config jest.config.mjs",
|
|
19
|
+
"lint": "tsc --noEmit",
|
|
20
|
+
"preversion": "npm run lint && npm run build"
|
|
21
|
+
},
|
|
22
|
+
"author": "",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/jest": "^30.0.0",
|
|
29
|
+
"jest": "^30.2.0",
|
|
30
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
31
|
+
"jest-fetch-mock": "^3.0.3",
|
|
32
|
+
"ts-jest": "^29.4.6",
|
|
33
|
+
"tsup": "^8.5.1",
|
|
34
|
+
"typescript": "^5.9.3"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
41
|
+
"zod": "^4.3.5"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@joai/warps": "^3.0.0-beta.198"
|
|
45
|
+
}
|
|
46
|
+
}
|