claw-xiaowan 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ocean
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # OmniClaw MCP Server Plugin
2
+
3
+ OpenClaw plugin for integrating MCP (Model Context Protocol) servers as agent tools.
4
+
5
+ ## Features
6
+
7
+ - Connect to multiple MCP servers
8
+ - Register MCP tools as native OpenClaw agent tools
9
+ - Configuration-based server management
10
+ - Connection status monitoring
11
+ - CLI commands for server management
12
+
13
+ ## Installation
14
+
15
+ ### Local Development
16
+
17
+ ```bash
18
+ # Link this plugin to your OpenClaw extensions
19
+ openclaw plugins install -l /Users/ocean/code/OmniClawPlugin
20
+
21
+ # Restart the gateway
22
+ openclaw gateway restart
23
+ ```
24
+
25
+ ### From npm (when published)
26
+
27
+ ```bash
28
+ openclaw plugins install @omniclaw/mcp-server
29
+ openclaw gateway restart
30
+ ```
31
+
32
+ ## Configuration
33
+
34
+ Add to your OpenClaw config:
35
+
36
+ ```json5
37
+ {
38
+ plugins: {
39
+ entries: {
40
+ "mcp-server": {
41
+ enabled: true,
42
+ config: {
43
+ servers: [
44
+ {
45
+ id: "filesystem",
46
+ name: "Filesystem Tools",
47
+ url: "npx -y @modelcontextprotocol/server-filesystem /tmp",
48
+ enabled: true
49
+ },
50
+ {
51
+ id: "my-custom-server",
52
+ name: "My Custom Server",
53
+ url: "http://localhost:3000/sse",
54
+ token: "your-auth-token",
55
+ enabled: true
56
+ }
57
+ ]
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ ## Server URL Schemes
66
+
67
+ The plugin supports different connection methods based on the URL:
68
+
69
+ - **Local executable**: `npx -y @modelcontextprotocol/server-filesystem /tmp`
70
+ - **HTTP/SSE**: `http://localhost:3000/sse` or `https://api.example.com/mcp`
71
+ - **WebSocket**: `ws://localhost:3000/ws` or `wss://api.example.com/ws`
72
+
73
+ ## Usage
74
+
75
+ ### CLI Commands
76
+
77
+ ```bash
78
+ # List configured MCP servers
79
+ openclaw mcp --list
80
+
81
+ # Check server status
82
+ openclaw mcp --status
83
+ ```
84
+
85
+ ### Agent Tools
86
+
87
+ Once configured, MCP tools are available to OpenClaw agents as:
88
+
89
+ ```
90
+ mcp_<server-id>_<tool-name>
91
+ ```
92
+
93
+ For example, if you have a `filesystem` server with a `read_file` tool, agents can call:
94
+
95
+ ```
96
+ mcp_filesystem_read_file
97
+ ```
98
+
99
+ ### Gateway RPC
100
+
101
+ ```bash
102
+ # Get MCP server status via RPC
103
+ openclaw gateway rpc mcp.status
104
+ ```
105
+
106
+ ## Development
107
+
108
+ ```bash
109
+ # Install dependencies
110
+ npm install
111
+
112
+ # Build the plugin
113
+ npm run build
114
+
115
+ # Watch for changes
116
+ npm run dev
117
+ ```
118
+
119
+ ## Supported MCP Servers
120
+
121
+ This plugin should work with any MCP-compliant server. Known examples:
122
+
123
+ - `@modelcontextprotocol/server-filesystem` - Filesystem operations
124
+ - `@modelcontextprotocol/server-git` - Git operations
125
+ - Custom MCP servers
126
+
127
+ ## License
128
+
129
+ MIT
@@ -0,0 +1,10 @@
1
+ import { McpPlugin } from "./mcp-plugin.js";
2
+ /**
3
+ * MCP Server Plugin for OpenClaw
4
+ *
5
+ * This plugin integrates MCP (Model Context Protocol) servers as OpenClaw agent tools.
6
+ * It allows OpenClaw agents to call MCP tools as if they were native tools.
7
+ */
8
+ export default function register(api: any): void;
9
+ export { McpPlugin };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QAGxC;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ import { McpPlugin } from "./mcp-plugin.js";
2
+ /**
3
+ * MCP Server Plugin for OpenClaw
4
+ *
5
+ * This plugin integrates MCP (Model Context Protocol) servers as OpenClaw agent tools.
6
+ * It allows OpenClaw agents to call MCP tools as if they were native tools.
7
+ */
8
+ export default function register(api) {
9
+ const plugin = new McpPlugin(api);
10
+ plugin.register();
11
+ }
12
+ export { McpPlugin };
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAQ;IACvC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,CAAC,QAAQ,EAAE,CAAC;AACpB,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ /**
3
+ * MCP Client Manager
4
+ *
5
+ * Manages connections to multiple MCP servers
6
+ */
7
+ export declare class McpClientManager {
8
+ private api;
9
+ private clients;
10
+ private transports;
11
+ constructor(api: any);
12
+ /**
13
+ * Connect to an MCP server
14
+ */
15
+ connect(serverConfig: any): Promise<Client>;
16
+ /**
17
+ * Disconnect from an MCP server
18
+ */
19
+ disconnect(serverId: string): Promise<void>;
20
+ /**
21
+ * Check if a server is connected
22
+ */
23
+ isConnected(serverId: string): Promise<boolean>;
24
+ /**
25
+ * Get a client by server ID
26
+ */
27
+ getClient(serverId: string): Client | undefined;
28
+ /**
29
+ * Disconnect all servers
30
+ */
31
+ disconnectAll(): Promise<void>;
32
+ /**
33
+ * Create WebSocket transport (custom implementation)
34
+ * Note: This is a placeholder - actual WebSocket transport implementation may vary
35
+ */
36
+ private createWebSocketTransport;
37
+ }
38
+ //# sourceMappingURL=mcp-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKnE;;;;GAIG;AACH,qBAAa,gBAAgB;IAIf,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,UAAU,CAA+B;gBAE7B,GAAG,EAAE,GAAG;IAE5B;;OAEG;IACG,OAAO,CAAC,YAAY,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IA+DjD;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBjD;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAarD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI/C;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAKpC;;;OAGG;YACW,wBAAwB;CAMvC"}
@@ -0,0 +1,138 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
4
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5
+ /**
6
+ * MCP Client Manager
7
+ *
8
+ * Manages connections to multiple MCP servers
9
+ */
10
+ export class McpClientManager {
11
+ api;
12
+ clients = new Map();
13
+ transports = new Map();
14
+ constructor(api) {
15
+ this.api = api;
16
+ }
17
+ /**
18
+ * Connect to an MCP server
19
+ */
20
+ async connect(serverConfig) {
21
+ const { id, url, token, type } = serverConfig;
22
+ // Check if already connected
23
+ if (this.clients.has(id)) {
24
+ const existingClient = this.clients.get(id);
25
+ if (await this.isConnected(id)) {
26
+ return existingClient;
27
+ }
28
+ // Clean up disconnected client
29
+ await this.disconnect(id);
30
+ }
31
+ // Create new client
32
+ const client = new Client({
33
+ name: `openclaw-mcp-${id}`,
34
+ version: "1.0.0",
35
+ }, {
36
+ capabilities: {},
37
+ });
38
+ // Create transport based on URL scheme or type
39
+ let transport;
40
+ if (type === "streamablehttp") {
41
+ // Streamable HTTP transport with Bearer auth
42
+ transport = new StreamableHTTPClientTransport(new URL(url), {
43
+ requestInit: {
44
+ headers: {
45
+ "Authorization": `Bearer ${token}`,
46
+ "Content-Type": "application/json"
47
+ }
48
+ }
49
+ });
50
+ }
51
+ else if (url.startsWith("http://") || url.startsWith("https://")) {
52
+ // SSE transport
53
+ transport = new SSEClientTransport(new URL(url));
54
+ }
55
+ else if (url.startsWith("ws://") || url.startsWith("wss://")) {
56
+ // WebSocket transport (requires custom implementation)
57
+ transport = await this.createWebSocketTransport(url, token);
58
+ }
59
+ else {
60
+ // Assume stdio transport for local executables
61
+ transport = new StdioClientTransport({
62
+ command: url,
63
+ args: token ? ["--token", token] : [],
64
+ });
65
+ }
66
+ this.transports.set(id, transport);
67
+ // Connect
68
+ await client.connect(transport);
69
+ this.clients.set(id, client);
70
+ this.api.logger.info(`Connected to MCP server: ${id}`);
71
+ return client;
72
+ }
73
+ /**
74
+ * Disconnect from an MCP server
75
+ */
76
+ async disconnect(serverId) {
77
+ const client = this.clients.get(serverId);
78
+ if (client) {
79
+ try {
80
+ await client.close();
81
+ }
82
+ catch (e) {
83
+ this.api.logger.warn(`Error closing MCP client ${serverId}:`, e);
84
+ }
85
+ this.clients.delete(serverId);
86
+ }
87
+ const transport = this.transports.get(serverId);
88
+ if (transport) {
89
+ try {
90
+ await transport.close();
91
+ }
92
+ catch (e) {
93
+ this.api.logger.warn(`Error closing MCP transport ${serverId}:`, e);
94
+ }
95
+ this.transports.delete(serverId);
96
+ }
97
+ }
98
+ /**
99
+ * Check if a server is connected
100
+ */
101
+ async isConnected(serverId) {
102
+ const client = this.clients.get(serverId);
103
+ if (!client)
104
+ return false;
105
+ try {
106
+ // Try to ping the server
107
+ const response = await client.ping();
108
+ return !!response;
109
+ }
110
+ catch (e) {
111
+ return false;
112
+ }
113
+ }
114
+ /**
115
+ * Get a client by server ID
116
+ */
117
+ getClient(serverId) {
118
+ return this.clients.get(serverId);
119
+ }
120
+ /**
121
+ * Disconnect all servers
122
+ */
123
+ async disconnectAll() {
124
+ const serverIds = Array.from(this.clients.keys());
125
+ await Promise.all(serverIds.map((id) => this.disconnect(id)));
126
+ }
127
+ /**
128
+ * Create WebSocket transport (custom implementation)
129
+ * Note: This is a placeholder - actual WebSocket transport implementation may vary
130
+ */
131
+ async createWebSocketTransport(url, token) {
132
+ // TODO: Implement WebSocket transport
133
+ // The MCP SDK may not have built-in WebSocket support yet
134
+ // This would require a custom transport implementation
135
+ throw new Error("WebSocket transport not yet implemented. Use SSE or stdio.");
136
+ }
137
+ }
138
+ //# sourceMappingURL=mcp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Main MCP Plugin class
3
+ *
4
+ * Manages MCP client connections and tool registration with OpenClaw
5
+ */
6
+ export declare class McpPlugin {
7
+ private api;
8
+ private clientManager;
9
+ private toolRegistrar;
10
+ constructor(api: any);
11
+ register(): void;
12
+ private getStatus;
13
+ private listServers;
14
+ private showStatus;
15
+ }
16
+ //# sourceMappingURL=mcp-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-plugin.d.ts","sourceRoot":"","sources":["../src/mcp-plugin.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,qBAAa,SAAS;IAIR,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,aAAa,CAAmB;IACxC,OAAO,CAAC,aAAa,CAAgB;gBAEjB,GAAG,EAAE,GAAG;IAK5B,QAAQ;YA+BM,SAAS;YAgBT,WAAW;YAYX,UAAU;CAOzB"}
@@ -0,0 +1,79 @@
1
+ import { McpClientManager } from "./mcp-client.js";
2
+ import { ToolRegistrar } from "./tools.js";
3
+ /**
4
+ * Main MCP Plugin class
5
+ *
6
+ * Manages MCP client connections and tool registration with OpenClaw
7
+ */
8
+ export class McpPlugin {
9
+ api;
10
+ clientManager;
11
+ toolRegistrar;
12
+ constructor(api) {
13
+ this.api = api;
14
+ this.clientManager = new McpClientManager(api);
15
+ this.toolRegistrar = new ToolRegistrar(api, this.clientManager);
16
+ }
17
+ register() {
18
+ // Register all MCP servers as tools
19
+ this.toolRegistrar.registerTools();
20
+ // Register gateway RPC method for status
21
+ this.api.registerGatewayMethod("mcp.status", async ({ respond }) => {
22
+ const status = await this.getStatus();
23
+ respond(true, status);
24
+ });
25
+ // Register CLI commands
26
+ this.api.registerCli(({ program }) => {
27
+ program
28
+ .command("mcp")
29
+ .description("Manage MCP servers")
30
+ .option("--list", "List configured MCP servers")
31
+ .option("--status", "Show MCP server status")
32
+ .action(async (options) => {
33
+ if (options.list) {
34
+ await this.listServers();
35
+ }
36
+ else if (options.status) {
37
+ await this.showStatus();
38
+ }
39
+ else {
40
+ console.log("Use --list or --status");
41
+ }
42
+ });
43
+ }, { commands: ["mcp"] });
44
+ this.api.logger.info("MCP Server plugin registered");
45
+ }
46
+ async getStatus() {
47
+ const config = this.api.config.plugins?.entries?.["xiaowan"]?.config || {};
48
+ const servers = config.servers || [];
49
+ return {
50
+ ok: true,
51
+ servers: servers.map((server) => ({
52
+ id: server.id,
53
+ name: server.name || server.id,
54
+ enabled: server.enabled !== false,
55
+ url: server.url,
56
+ connected: this.clientManager.isConnected(server.id),
57
+ })),
58
+ };
59
+ }
60
+ async listServers() {
61
+ const status = await this.getStatus();
62
+ console.log("\n=== MCP Servers ===");
63
+ status.servers.forEach((server) => {
64
+ const icon = server.enabled ? "✓" : "✗";
65
+ const conn = server.connected ? "connected" : "disconnected";
66
+ console.log(`${icon} ${server.name} (${server.id}) - ${conn}`);
67
+ console.log(` URL: ${server.url}`);
68
+ });
69
+ console.log();
70
+ }
71
+ async showStatus() {
72
+ const status = await this.getStatus();
73
+ console.log("\n=== MCP Status ===");
74
+ console.log(`Total servers: ${status.servers.length}`);
75
+ console.log(`Connected: ${status.servers.filter((s) => s.connected).length}`);
76
+ console.log();
77
+ }
78
+ }
79
+ //# sourceMappingURL=mcp-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-plugin.js","sourceRoot":"","sources":["../src/mcp-plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { McpClientManager } from "./mcp-client.js";
2
+ /**
3
+ * Tool Registrar
4
+ *
5
+ * Registers MCP tools as OpenClaw agent tools
6
+ */
7
+ export declare class ToolRegistrar {
8
+ private api;
9
+ private clientManager;
10
+ constructor(api: any, clientManager: McpClientManager);
11
+ /**
12
+ * Register all configured MCP servers as tools
13
+ */
14
+ registerTools(): Promise<void>;
15
+ /**
16
+ * Register tools from a single MCP server
17
+ */
18
+ private registerServerTools;
19
+ /**
20
+ * Register a single MCP tool as an OpenClaw tool
21
+ */
22
+ private registerMcpTool;
23
+ /**
24
+ * Sanitize tool name to be valid identifier
25
+ */
26
+ private sanitizeToolName;
27
+ }
28
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;;GAIG;AACH,qBAAa,aAAa;IAEtB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,aAAa;gBADb,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,gBAAgB;IAGzC;;OAEG;IACG,aAAa;IAiBnB;;OAEG;YACW,mBAAmB;IAajC;;OAEG;IACH,OAAO,CAAC,eAAe;IAuCvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAOzB"}
package/dist/tools.js ADDED
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Tool Registrar
3
+ *
4
+ * Registers MCP tools as OpenClaw agent tools
5
+ */
6
+ export class ToolRegistrar {
7
+ api;
8
+ clientManager;
9
+ constructor(api, clientManager) {
10
+ this.api = api;
11
+ this.clientManager = clientManager;
12
+ }
13
+ /**
14
+ * Register all configured MCP servers as tools
15
+ */
16
+ async registerTools() {
17
+ const config = this.api.config.plugins?.entries?.["xiaowan"]?.config || {};
18
+ const servers = config.servers || [];
19
+ for (const server of servers) {
20
+ if (server.enabled === false) {
21
+ continue;
22
+ }
23
+ try {
24
+ await this.registerServerTools(server);
25
+ }
26
+ catch (e) {
27
+ this.api.logger.error(`Failed to register tools for MCP server ${server.id}:`, e);
28
+ }
29
+ }
30
+ }
31
+ /**
32
+ * Register tools from a single MCP server
33
+ */
34
+ async registerServerTools(server) {
35
+ const client = await this.clientManager.connect(server);
36
+ // List available tools from the MCP server
37
+ const toolsResponse = await client.listTools();
38
+ for (const mcpTool of toolsResponse.tools) {
39
+ this.registerMcpTool(server, client, mcpTool);
40
+ }
41
+ this.api.logger.info(`Registered ${toolsResponse.tools.length} tools from MCP server: ${server.id}`);
42
+ }
43
+ /**
44
+ * Register a single MCP tool as an OpenClaw tool
45
+ */
46
+ registerMcpTool(server, client, mcpTool) {
47
+ const toolId = `mcp_${server.id}_${mcpTool.name}`;
48
+ const toolName = this.sanitizeToolName(mcpTool.name);
49
+ const tool = {
50
+ name: toolName,
51
+ description: mcpTool.description || `MCP tool: ${mcpTool.name} from ${server.name || server.id}`,
52
+ inputSchema: mcpTool.inputSchema,
53
+ handler: async (params) => {
54
+ try {
55
+ // Ensure client is connected
56
+ if (!(await this.clientManager.isConnected(server.id))) {
57
+ await this.clientManager.connect(server);
58
+ }
59
+ // Call the MCP tool
60
+ const response = await client.callTool({
61
+ name: mcpTool.name,
62
+ arguments: params,
63
+ });
64
+ // Format the response for OpenClaw
65
+ return {
66
+ content: response.content,
67
+ isError: response.isError,
68
+ };
69
+ }
70
+ catch (e) {
71
+ this.api.logger.error(`Error calling MCP tool ${toolName}:`, e);
72
+ throw e;
73
+ }
74
+ },
75
+ };
76
+ // Register the tool with OpenClaw
77
+ this.api.registerTool(tool);
78
+ this.api.logger.debug(`Registered tool: ${toolName}`);
79
+ }
80
+ /**
81
+ * Sanitize tool name to be valid identifier
82
+ */
83
+ sanitizeToolName(name) {
84
+ return name
85
+ .toLowerCase()
86
+ .replace(/[^a-z0-9_]/g, "_")
87
+ .replace(/_{2,}/g, "_")
88
+ .replace(/^_|_$/g, "");
89
+ }
90
+ }
91
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "claw-xiaowan",
3
+ "version": "0.1.0",
4
+ "description": "OpenClaw plugin for MCP (Model Context Protocol) server integration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "prepack": "npm run build"
17
+ },
18
+ "openclaw": {
19
+ "extensions": ["./src/index.ts"]
20
+ },
21
+ "dependencies": {
22
+ "@modelcontextprotocol/sdk": "^1.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^20.0.0",
26
+ "openclaw": "latest",
27
+ "typescript": "^5.0.0"
28
+ },
29
+ "keywords": [
30
+ "openclaw",
31
+ "plugin",
32
+ "mcp",
33
+ "model-context-protocol",
34
+ "mcp-server"
35
+ ],
36
+ "author": "y-shi23 <https://github.com/y-shi23>",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/y-shi23/OmniClawPlugin.git"
41
+ },
42
+ "homepage": "https://github.com/y-shi23/OmniClawPlugin#readme",
43
+ "bugs": {
44
+ "url": "https://github.com/y-shi23/OmniClawPlugin/issues"
45
+ }
46
+ }