@jacob2826/openclaw-dida365-mcp 0.2.2
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/CHANGELOG.md +25 -0
- package/LICENSE +674 -0
- package/README.md +203 -0
- package/SECURITY.md +58 -0
- package/data/mcp-tools.json +7691 -0
- package/dist/bridge.d.ts +77 -0
- package/dist/bridge.js +193 -0
- package/dist/bridge.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.js +45 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +83 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +12 -0
- package/dist/manifest.js +67 -0
- package/dist/manifest.js.map +1 -0
- package/dist/runtime-state.d.ts +4 -0
- package/dist/runtime-state.js +50 -0
- package/dist/runtime-state.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/openclaw.plugin.json +70 -0
- package/package.json +70 -0
package/dist/bridge.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { RemoteToolDefinition } from "./types.js";
|
|
2
|
+
export interface BridgeLogger {
|
|
3
|
+
info?: (message: string) => void;
|
|
4
|
+
warn?: (message: string) => void;
|
|
5
|
+
error?: (message: string) => void;
|
|
6
|
+
debug?: (message: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export interface BridgeTransportLike {
|
|
9
|
+
stderr?: unknown;
|
|
10
|
+
onclose?: () => void;
|
|
11
|
+
onerror?: (error: Error) => void;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export interface BridgeClientLike {
|
|
15
|
+
listTools(params?: unknown, options?: {
|
|
16
|
+
timeout?: number;
|
|
17
|
+
resetTimeoutOnProgress?: boolean;
|
|
18
|
+
maxTotalTimeout?: number;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
tools?: Array<{
|
|
21
|
+
name: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
inputSchema?: Record<string, unknown>;
|
|
24
|
+
outputSchema?: Record<string, unknown>;
|
|
25
|
+
annotations?: Record<string, unknown>;
|
|
26
|
+
execution?: Record<string, unknown>;
|
|
27
|
+
title?: string;
|
|
28
|
+
}>;
|
|
29
|
+
}>;
|
|
30
|
+
callTool(params: {
|
|
31
|
+
name: string;
|
|
32
|
+
arguments?: Record<string, unknown>;
|
|
33
|
+
}, resultSchema?: unknown, options?: {
|
|
34
|
+
timeout?: number;
|
|
35
|
+
resetTimeoutOnProgress?: boolean;
|
|
36
|
+
maxTotalTimeout?: number;
|
|
37
|
+
}): Promise<unknown>;
|
|
38
|
+
close(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export interface BridgeConnection {
|
|
41
|
+
client: BridgeClientLike;
|
|
42
|
+
transport: BridgeTransportLike;
|
|
43
|
+
}
|
|
44
|
+
export interface BridgeOptions {
|
|
45
|
+
serverUrl: string;
|
|
46
|
+
command: string;
|
|
47
|
+
args: string[];
|
|
48
|
+
host: string;
|
|
49
|
+
authTimeoutSeconds: number;
|
|
50
|
+
requestTimeoutSeconds: number;
|
|
51
|
+
toolAllowlist?: string[];
|
|
52
|
+
toolDenylist?: string[];
|
|
53
|
+
idleTimeoutSeconds: number;
|
|
54
|
+
env?: NodeJS.ProcessEnv;
|
|
55
|
+
logger?: BridgeLogger;
|
|
56
|
+
connectRuntime?: (options: BridgeOptions, logger?: BridgeLogger) => Promise<BridgeConnection>;
|
|
57
|
+
}
|
|
58
|
+
export declare class Dida365Bridge {
|
|
59
|
+
private readonly options;
|
|
60
|
+
private logger;
|
|
61
|
+
private client;
|
|
62
|
+
private transport;
|
|
63
|
+
private connectPromise;
|
|
64
|
+
private activeRequests;
|
|
65
|
+
private idleTimer;
|
|
66
|
+
constructor(options: BridgeOptions);
|
|
67
|
+
listTools(): Promise<RemoteToolDefinition[]>;
|
|
68
|
+
callTool(name: string, args: Record<string, unknown> | undefined): Promise<unknown>;
|
|
69
|
+
setLogger(logger: BridgeLogger | undefined): void;
|
|
70
|
+
close(): Promise<void>;
|
|
71
|
+
private connect;
|
|
72
|
+
private connectInternal;
|
|
73
|
+
private withClient;
|
|
74
|
+
private scheduleIdleClose;
|
|
75
|
+
private clearIdleTimer;
|
|
76
|
+
}
|
|
77
|
+
export declare function redactSensitiveText(text: string): string;
|
package/dist/bridge.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
4
|
+
export class Dida365Bridge {
|
|
5
|
+
options;
|
|
6
|
+
logger;
|
|
7
|
+
client = null;
|
|
8
|
+
transport = null;
|
|
9
|
+
connectPromise = null;
|
|
10
|
+
activeRequests = 0;
|
|
11
|
+
idleTimer = null;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.options = options;
|
|
14
|
+
this.logger = options.logger;
|
|
15
|
+
}
|
|
16
|
+
async listTools() {
|
|
17
|
+
return this.withClient(async (client) => {
|
|
18
|
+
const result = await client.listTools(undefined, {
|
|
19
|
+
timeout: this.options.requestTimeoutSeconds * 1000,
|
|
20
|
+
resetTimeoutOnProgress: true,
|
|
21
|
+
maxTotalTimeout: this.options.requestTimeoutSeconds * 1000,
|
|
22
|
+
});
|
|
23
|
+
return (result.tools ?? []).map((tool) => ({
|
|
24
|
+
name: tool.name,
|
|
25
|
+
description: tool.description,
|
|
26
|
+
inputSchema: tool.inputSchema,
|
|
27
|
+
outputSchema: tool.outputSchema,
|
|
28
|
+
annotations: tool.annotations,
|
|
29
|
+
execution: tool.execution,
|
|
30
|
+
title: tool.title,
|
|
31
|
+
}));
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async callTool(name, args) {
|
|
35
|
+
return this.withClient(async (client) => {
|
|
36
|
+
return client.callTool({
|
|
37
|
+
name,
|
|
38
|
+
arguments: args ?? {},
|
|
39
|
+
}, undefined, {
|
|
40
|
+
timeout: this.options.requestTimeoutSeconds * 1000,
|
|
41
|
+
resetTimeoutOnProgress: true,
|
|
42
|
+
maxTotalTimeout: this.options.requestTimeoutSeconds * 1000,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
setLogger(logger) {
|
|
47
|
+
this.logger = logger;
|
|
48
|
+
}
|
|
49
|
+
async close() {
|
|
50
|
+
this.clearIdleTimer();
|
|
51
|
+
const client = this.client;
|
|
52
|
+
const transport = this.transport;
|
|
53
|
+
this.client = null;
|
|
54
|
+
this.transport = null;
|
|
55
|
+
this.connectPromise = null;
|
|
56
|
+
try {
|
|
57
|
+
await client?.close();
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await transport?.close();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async connect() {
|
|
64
|
+
if (this.client) {
|
|
65
|
+
return this.client;
|
|
66
|
+
}
|
|
67
|
+
if (!this.connectPromise) {
|
|
68
|
+
this.connectPromise = this.connectInternal();
|
|
69
|
+
}
|
|
70
|
+
return this.connectPromise;
|
|
71
|
+
}
|
|
72
|
+
async connectInternal() {
|
|
73
|
+
const connection = this.options.connectRuntime
|
|
74
|
+
? await this.options.connectRuntime(this.options, this.logger)
|
|
75
|
+
: await connectWithSdk(this.options, this.logger);
|
|
76
|
+
const { client, transport } = connection;
|
|
77
|
+
attachTransportHooks(transport, () => this.logger, () => {
|
|
78
|
+
this.clearIdleTimer();
|
|
79
|
+
this.client = null;
|
|
80
|
+
this.transport = null;
|
|
81
|
+
this.connectPromise = null;
|
|
82
|
+
});
|
|
83
|
+
this.transport = transport;
|
|
84
|
+
this.client = client;
|
|
85
|
+
return client;
|
|
86
|
+
}
|
|
87
|
+
async withClient(fn) {
|
|
88
|
+
this.clearIdleTimer();
|
|
89
|
+
this.activeRequests += 1;
|
|
90
|
+
try {
|
|
91
|
+
const client = await this.connect();
|
|
92
|
+
return await fn(client);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
this.activeRequests = Math.max(0, this.activeRequests - 1);
|
|
96
|
+
if (this.activeRequests === 0) {
|
|
97
|
+
this.scheduleIdleClose();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
scheduleIdleClose() {
|
|
102
|
+
this.clearIdleTimer();
|
|
103
|
+
if (this.options.idleTimeoutSeconds <= 0 || !this.client || !this.transport) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const timeoutMs = this.options.idleTimeoutSeconds * 1000;
|
|
107
|
+
this.idleTimer = setTimeout(() => {
|
|
108
|
+
if (this.activeRequests !== 0) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.logger?.info?.(`closing idle mcp-remote transport after ${this.options.idleTimeoutSeconds}s`);
|
|
112
|
+
void this.close();
|
|
113
|
+
}, timeoutMs);
|
|
114
|
+
this.idleTimer.unref?.();
|
|
115
|
+
}
|
|
116
|
+
clearIdleTimer() {
|
|
117
|
+
if (this.idleTimer) {
|
|
118
|
+
clearTimeout(this.idleTimer);
|
|
119
|
+
this.idleTimer = null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function connectWithSdk(options, logger) {
|
|
124
|
+
const transport = new StdioClientTransport({
|
|
125
|
+
command: options.command,
|
|
126
|
+
args: [
|
|
127
|
+
...options.args,
|
|
128
|
+
options.serverUrl,
|
|
129
|
+
"--host",
|
|
130
|
+
options.host,
|
|
131
|
+
"--auth-timeout",
|
|
132
|
+
String(options.authTimeoutSeconds),
|
|
133
|
+
],
|
|
134
|
+
env: {
|
|
135
|
+
...stringifyEnv({
|
|
136
|
+
...process.env,
|
|
137
|
+
...options.env,
|
|
138
|
+
}),
|
|
139
|
+
},
|
|
140
|
+
stderr: "pipe",
|
|
141
|
+
});
|
|
142
|
+
pipeStderr(transport.stderr, logger);
|
|
143
|
+
const client = new Client({
|
|
144
|
+
name: "openclaw-dida365-mcp",
|
|
145
|
+
version: "0.2.0",
|
|
146
|
+
}, {
|
|
147
|
+
capabilities: {},
|
|
148
|
+
});
|
|
149
|
+
await client.connect(transport, {
|
|
150
|
+
timeout: options.requestTimeoutSeconds * 1000,
|
|
151
|
+
resetTimeoutOnProgress: true,
|
|
152
|
+
maxTotalTimeout: options.requestTimeoutSeconds * 1000,
|
|
153
|
+
});
|
|
154
|
+
return {
|
|
155
|
+
client,
|
|
156
|
+
transport,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function attachTransportHooks(transport, getLogger, onClose) {
|
|
160
|
+
const previousOnClose = transport.onclose;
|
|
161
|
+
const previousOnError = transport.onerror;
|
|
162
|
+
transport.onerror = (error) => {
|
|
163
|
+
previousOnError?.(error);
|
|
164
|
+
getLogger()?.error?.(`mcp-remote transport error: ${String(error)}`);
|
|
165
|
+
};
|
|
166
|
+
transport.onclose = () => {
|
|
167
|
+
previousOnClose?.();
|
|
168
|
+
getLogger()?.warn?.("mcp-remote transport closed");
|
|
169
|
+
onClose();
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function pipeStderr(stream, logger) {
|
|
173
|
+
if (!stream || typeof stream !== "object" || !("on" in stream) || typeof stream.on !== "function") {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
stream.on("data", (chunk) => {
|
|
177
|
+
const text = redactSensitiveText(String(chunk).trim());
|
|
178
|
+
if (!text) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
logger?.info?.(text);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
export function redactSensitiveText(text) {
|
|
185
|
+
return text
|
|
186
|
+
.replace(/"access_token"\s*:\s*"[^"]+"/gi, '"access_token":"REDACTED"')
|
|
187
|
+
.replace(/"refresh_token"\s*:\s*"[^"]+"/gi, '"refresh_token":"REDACTED"')
|
|
188
|
+
.replace(/"id_token"\s*:\s*"[^"]+"/gi, '"id_token":"REDACTED"');
|
|
189
|
+
}
|
|
190
|
+
function stringifyEnv(env) {
|
|
191
|
+
return Object.fromEntries(Object.entries(env).filter((entry) => typeof entry[1] === "string"));
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface Dida365PluginConfig {
|
|
2
|
+
serverUrl?: string;
|
|
3
|
+
command?: string;
|
|
4
|
+
args?: string[];
|
|
5
|
+
host?: string;
|
|
6
|
+
authTimeoutSeconds?: number;
|
|
7
|
+
requestTimeoutSeconds?: number;
|
|
8
|
+
toolAllowlist?: string[];
|
|
9
|
+
toolDenylist?: string[];
|
|
10
|
+
idleTimeoutSeconds?: number;
|
|
11
|
+
refreshManifestOnStartup?: boolean;
|
|
12
|
+
manifestPath?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ResolvedPluginConfig {
|
|
15
|
+
serverUrl: string;
|
|
16
|
+
command: string;
|
|
17
|
+
args: string[];
|
|
18
|
+
host: string;
|
|
19
|
+
authTimeoutSeconds: number;
|
|
20
|
+
requestTimeoutSeconds: number;
|
|
21
|
+
toolAllowlist: string[];
|
|
22
|
+
toolDenylist: string[];
|
|
23
|
+
idleTimeoutSeconds: number;
|
|
24
|
+
refreshManifestOnStartup: boolean;
|
|
25
|
+
manifestPath: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function resolvePluginConfig(pluginConfig: Dida365PluginConfig | null | undefined, pluginRoot: string): ResolvedPluginConfig;
|
|
28
|
+
export declare function assertSafePluginConfig(config: ResolvedPluginConfig): void;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function resolvePluginConfig(pluginConfig, pluginRoot) {
|
|
3
|
+
const cfg = pluginConfig ?? {};
|
|
4
|
+
return {
|
|
5
|
+
serverUrl: cfg.serverUrl ?? "https://mcp.dida365.com",
|
|
6
|
+
command: cfg.command ?? "npx",
|
|
7
|
+
args: cfg.args ?? ["-y", "mcp-remote@latest"],
|
|
8
|
+
host: cfg.host ?? "127.0.0.1",
|
|
9
|
+
authTimeoutSeconds: cfg.authTimeoutSeconds ?? 300,
|
|
10
|
+
requestTimeoutSeconds: cfg.requestTimeoutSeconds ?? 300,
|
|
11
|
+
toolAllowlist: normalizeToolList(cfg.toolAllowlist),
|
|
12
|
+
toolDenylist: normalizeToolList(cfg.toolDenylist),
|
|
13
|
+
idleTimeoutSeconds: cfg.idleTimeoutSeconds ?? 600,
|
|
14
|
+
refreshManifestOnStartup: cfg.refreshManifestOnStartup ?? false,
|
|
15
|
+
manifestPath: cfg.manifestPath
|
|
16
|
+
? path.resolve(cfg.manifestPath)
|
|
17
|
+
: path.join(pluginRoot, "data", "mcp-tools.json"),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function assertSafePluginConfig(config) {
|
|
21
|
+
if (!config.command.trim()) {
|
|
22
|
+
throw new Error("Plugin command cannot be empty.");
|
|
23
|
+
}
|
|
24
|
+
if (config.args.some((arg) => !arg.trim())) {
|
|
25
|
+
throw new Error("Plugin command args cannot contain empty strings.");
|
|
26
|
+
}
|
|
27
|
+
let url;
|
|
28
|
+
try {
|
|
29
|
+
url = new URL(config.serverUrl);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw new Error(`Invalid serverUrl: ${String(error)}`);
|
|
33
|
+
}
|
|
34
|
+
const hostname = url.hostname.toLowerCase();
|
|
35
|
+
const isLoopback = hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
|
|
36
|
+
const isSecureRemote = url.protocol === "https:";
|
|
37
|
+
const isLoopbackHttp = isLoopback && url.protocol === "http:";
|
|
38
|
+
if (!isSecureRemote && !isLoopbackHttp) {
|
|
39
|
+
throw new Error(`Refusing unsafe serverUrl ${config.serverUrl}. Use https:// for remote MCP servers or http:// only for loopback development.`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function normalizeToolList(list) {
|
|
43
|
+
return [...new Set((list ?? []).map((item) => item.trim()).filter(Boolean))];
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AA8B7B,MAAM,UAAU,mBAAmB,CACjC,YAAoD,EACpD,UAAkB;IAElB,MAAM,GAAG,GAAG,YAAY,IAAI,EAAE,CAAC;IAC/B,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,yBAAyB;QACrD,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,KAAK;QAC7B,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,mBAAmB,CAAC;QAC7C,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,WAAW;QAC7B,kBAAkB,EAAE,GAAG,CAAC,kBAAkB,IAAI,GAAG;QACjD,qBAAqB,EAAE,GAAG,CAAC,qBAAqB,IAAI,GAAG;QACvD,aAAa,EAAE,iBAAiB,CAAC,GAAG,CAAC,aAAa,CAAC;QACnD,YAAY,EAAE,iBAAiB,CAAC,GAAG,CAAC,YAAY,CAAC;QACjD,kBAAkB,EAAE,GAAG,CAAC,kBAAkB,IAAI,GAAG;QACjD,wBAAwB,EAAE,GAAG,CAAC,wBAAwB,IAAI,KAAK;QAC/D,YAAY,EAAE,GAAG,CAAC,YAAY;YAC5B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAA4B;IACjE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,KAAK,CAAC;IAC9F,MAAM,cAAc,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACjD,MAAM,cAAc,GAAG,UAAU,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC;IAE9D,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CACb,6BAA6B,MAAM,CAAC,SAAS,iFAAiF,CAC/H,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,IAA0B;IACnD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC/E,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
interface OpenClawPluginApi {
|
|
2
|
+
pluginConfig?: Record<string, unknown>;
|
|
3
|
+
logger: {
|
|
4
|
+
info?: (message: string) => void;
|
|
5
|
+
warn?: (message: string) => void;
|
|
6
|
+
error?: (message: string) => void;
|
|
7
|
+
debug?: (message: string) => void;
|
|
8
|
+
};
|
|
9
|
+
registerTool: (tool: {
|
|
10
|
+
name: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
parameters?: Record<string, unknown>;
|
|
13
|
+
execute: (toolCallId: string, params: Record<string, unknown> | undefined) => Promise<unknown>;
|
|
14
|
+
}, options?: {
|
|
15
|
+
optional?: boolean;
|
|
16
|
+
names?: string[];
|
|
17
|
+
}) => void;
|
|
18
|
+
}
|
|
19
|
+
declare const plugin: {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
configSchema: {
|
|
24
|
+
type: string;
|
|
25
|
+
additionalProperties: boolean;
|
|
26
|
+
properties: {};
|
|
27
|
+
};
|
|
28
|
+
register(api: OpenClawPluginApi): void;
|
|
29
|
+
};
|
|
30
|
+
export default plugin;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { assertSafePluginConfig, resolvePluginConfig } from "./config.js";
|
|
5
|
+
import { loadToolsManifest, selectToolsFromManifest, writeToolsManifest } from "./manifest.js";
|
|
6
|
+
import { getSharedBridgeForConfig } from "./runtime-state.js";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const pluginRoot = path.resolve(__dirname, "..");
|
|
10
|
+
const plugin = {
|
|
11
|
+
id: "openclaw-dida365-mcp",
|
|
12
|
+
name: "Dida365 MCP",
|
|
13
|
+
description: "Expose official Dida365 MCP tools to OpenClaw's normal chat agent.",
|
|
14
|
+
configSchema: {
|
|
15
|
+
type: "object",
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
properties: {},
|
|
18
|
+
},
|
|
19
|
+
register(api) {
|
|
20
|
+
const config = resolvePluginConfig(api.pluginConfig, pluginRoot);
|
|
21
|
+
assertSafePluginConfig(config);
|
|
22
|
+
const bridge = getSharedBridgeForConfig(config, api.logger);
|
|
23
|
+
if (config.refreshManifestOnStartup) {
|
|
24
|
+
void bridge.listTools()
|
|
25
|
+
.then((tools) => {
|
|
26
|
+
writeToolsManifest(config.manifestPath, {
|
|
27
|
+
generatedAt: new Date().toISOString(),
|
|
28
|
+
serverUrl: config.serverUrl,
|
|
29
|
+
tools,
|
|
30
|
+
});
|
|
31
|
+
api.logger.info?.(`[openclaw-dida365-mcp] refreshed manifest at ${config.manifestPath}`);
|
|
32
|
+
})
|
|
33
|
+
.catch((error) => {
|
|
34
|
+
api.logger.warn?.(`[openclaw-dida365-mcp] manifest refresh failed on startup: ${String(error)}`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (!fs.existsSync(config.manifestPath)) {
|
|
38
|
+
api.logger.warn?.(`[openclaw-dida365-mcp] missing manifest ${config.manifestPath}; run npm run refresh-tools first`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const manifest = loadToolsManifest(config.manifestPath);
|
|
42
|
+
if (manifest.serverUrl && manifest.serverUrl !== config.serverUrl) {
|
|
43
|
+
api.logger.warn?.(`[openclaw-dida365-mcp] manifest serverUrl ${manifest.serverUrl} does not match active serverUrl ${config.serverUrl}`);
|
|
44
|
+
}
|
|
45
|
+
const selection = selectToolsFromManifest(manifest, {
|
|
46
|
+
allowlist: config.toolAllowlist,
|
|
47
|
+
denylist: config.toolDenylist,
|
|
48
|
+
});
|
|
49
|
+
for (const warning of selection.warnings) {
|
|
50
|
+
api.logger.warn?.(`[openclaw-dida365-mcp] ${warning}`);
|
|
51
|
+
}
|
|
52
|
+
if (selection.tools.length === 0) {
|
|
53
|
+
api.logger.warn?.("[openclaw-dida365-mcp] no tools selected from manifest");
|
|
54
|
+
}
|
|
55
|
+
for (const tool of selection.tools) {
|
|
56
|
+
api.registerTool({
|
|
57
|
+
name: tool.name,
|
|
58
|
+
description: buildToolDescription(tool),
|
|
59
|
+
parameters: tool.inputSchema,
|
|
60
|
+
async execute(_toolCallId, params) {
|
|
61
|
+
return bridge.callTool(tool.name, params);
|
|
62
|
+
},
|
|
63
|
+
}, { optional: true });
|
|
64
|
+
}
|
|
65
|
+
api.logger.info?.(`[openclaw-dida365-mcp] registered ${selection.tools.length} official tool(s) from ${path.basename(config.manifestPath)}`);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
export default plugin;
|
|
69
|
+
function buildToolDescription(tool) {
|
|
70
|
+
const base = tool.description ?? `Official Dida365 MCP tool: ${tool.name}`;
|
|
71
|
+
const hints = [];
|
|
72
|
+
if (tool.annotations?.readOnlyHint === true) {
|
|
73
|
+
hints.push("read-only");
|
|
74
|
+
}
|
|
75
|
+
if (tool.annotations?.destructiveHint === true) {
|
|
76
|
+
hints.push("destructive");
|
|
77
|
+
}
|
|
78
|
+
if (tool.annotations?.idempotentHint === true) {
|
|
79
|
+
hints.push("idempotent");
|
|
80
|
+
}
|
|
81
|
+
return hints.length > 0 ? `${base} [${hints.join(", ")}]` : base;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RemoteToolDefinition, RemoteToolsManifest } from "./types.js";
|
|
2
|
+
export declare function loadToolsManifest(manifestPath: string): RemoteToolsManifest;
|
|
3
|
+
export declare function writeToolsManifest(manifestPath: string, manifest: RemoteToolsManifest): void;
|
|
4
|
+
export interface ToolSelectionOptions {
|
|
5
|
+
allowlist?: string[];
|
|
6
|
+
denylist?: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface ToolSelectionResult {
|
|
9
|
+
tools: RemoteToolDefinition[];
|
|
10
|
+
warnings: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare function selectToolsFromManifest(manifest: RemoteToolsManifest, options?: ToolSelectionOptions): ToolSelectionResult;
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function loadToolsManifest(manifestPath) {
|
|
4
|
+
const raw = fs.readFileSync(manifestPath, "utf8");
|
|
5
|
+
const data = JSON.parse(raw);
|
|
6
|
+
if (!data || !Array.isArray(data.tools)) {
|
|
7
|
+
throw new Error(`Invalid tools manifest: ${manifestPath}`);
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
generatedAt: typeof data.generatedAt === "string" ? data.generatedAt : new Date(0).toISOString(),
|
|
11
|
+
serverUrl: typeof data.serverUrl === "string" ? data.serverUrl : "",
|
|
12
|
+
tools: data.tools
|
|
13
|
+
.filter((tool) => !!tool && typeof tool.name === "string")
|
|
14
|
+
.map((tool) => ({
|
|
15
|
+
name: tool.name,
|
|
16
|
+
description: tool.description,
|
|
17
|
+
inputSchema: normalizeSchema(tool.inputSchema),
|
|
18
|
+
outputSchema: normalizeSchema(tool.outputSchema),
|
|
19
|
+
annotations: tool.annotations,
|
|
20
|
+
execution: tool.execution,
|
|
21
|
+
title: tool.title,
|
|
22
|
+
})),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function writeToolsManifest(manifestPath, manifest) {
|
|
26
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
27
|
+
fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
28
|
+
}
|
|
29
|
+
function normalizeSchema(schema) {
|
|
30
|
+
if (!schema || typeof schema !== "object") {
|
|
31
|
+
return {
|
|
32
|
+
type: "object",
|
|
33
|
+
additionalProperties: true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return schema;
|
|
37
|
+
}
|
|
38
|
+
export function selectToolsFromManifest(manifest, options = {}) {
|
|
39
|
+
const allow = new Set(options.allowlist ?? []);
|
|
40
|
+
const deny = new Set(options.denylist ?? []);
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
const warnings = [];
|
|
43
|
+
const tools = [];
|
|
44
|
+
for (const tool of manifest.tools) {
|
|
45
|
+
if (!isSafeToolName(tool.name)) {
|
|
46
|
+
warnings.push(`Skipped unsafe tool name: ${tool.name}`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (seen.has(tool.name)) {
|
|
50
|
+
warnings.push(`Skipped duplicate tool name: ${tool.name}`);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
seen.add(tool.name);
|
|
54
|
+
if (allow.size > 0 && !allow.has(tool.name)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (deny.has(tool.name)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
tools.push(tool);
|
|
61
|
+
}
|
|
62
|
+
return { tools, warnings };
|
|
63
|
+
}
|
|
64
|
+
function isSafeToolName(name) {
|
|
65
|
+
return /^[a-z][a-z0-9_]*$/.test(name);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ResolvedPluginConfig } from "./config.js";
|
|
2
|
+
import { Dida365Bridge, type BridgeLogger, type BridgeOptions } from "./bridge.js";
|
|
3
|
+
export declare function getSharedBridgeForConfig(config: ResolvedPluginConfig, logger?: BridgeLogger, factory?: (options: BridgeOptions) => Dida365Bridge): Dida365Bridge;
|
|
4
|
+
export declare function resetSharedBridgeStateForTests(): Promise<void>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { Dida365Bridge } from "./bridge.js";
|
|
3
|
+
const STATE_KEY = Symbol.for("openclaw-dida365-mcp.shared-state");
|
|
4
|
+
export function getSharedBridgeForConfig(config, logger, factory = (options) => new Dida365Bridge(options)) {
|
|
5
|
+
const state = getState();
|
|
6
|
+
const configKey = JSON.stringify(config);
|
|
7
|
+
if (state.bridge && state.configKey === configKey) {
|
|
8
|
+
state.bridge.setLogger(logger);
|
|
9
|
+
return state.bridge;
|
|
10
|
+
}
|
|
11
|
+
if (state.bridge) {
|
|
12
|
+
void state.bridge.close();
|
|
13
|
+
}
|
|
14
|
+
const bridge = factory({
|
|
15
|
+
...config,
|
|
16
|
+
logger,
|
|
17
|
+
});
|
|
18
|
+
state.bridge = bridge;
|
|
19
|
+
state.configKey = configKey;
|
|
20
|
+
if (!state.exitHookInstalled) {
|
|
21
|
+
process.once("exit", () => {
|
|
22
|
+
const current = getState().bridge;
|
|
23
|
+
if (current) {
|
|
24
|
+
void current.close();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
state.exitHookInstalled = true;
|
|
28
|
+
}
|
|
29
|
+
return bridge;
|
|
30
|
+
}
|
|
31
|
+
export async function resetSharedBridgeStateForTests() {
|
|
32
|
+
const state = getState();
|
|
33
|
+
if (state.bridge) {
|
|
34
|
+
await state.bridge.close();
|
|
35
|
+
}
|
|
36
|
+
state.bridge = null;
|
|
37
|
+
state.configKey = null;
|
|
38
|
+
}
|
|
39
|
+
function getState() {
|
|
40
|
+
const globalRecord = globalThis;
|
|
41
|
+
if (!globalRecord[STATE_KEY]) {
|
|
42
|
+
globalRecord[STATE_KEY] = {
|
|
43
|
+
bridge: null,
|
|
44
|
+
configKey: null,
|
|
45
|
+
exitHookInstalled: false,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return globalRecord[STATE_KEY];
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=runtime-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-state.js","sourceRoot":"","sources":["../src/runtime-state.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAGnC,OAAO,EAAE,aAAa,EAAyC,MAAM,aAAa,CAAC;AAQnF,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;AAElE,MAAM,UAAU,wBAAwB,CACtC,MAA4B,EAC5B,MAAqB,EACrB,UAAqD,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC;IAE5F,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEzC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAClD,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC;QACrB,GAAG,MAAM;QACT,MAAM;KACP,CAAC,CAAC;IAEH,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IAE5B,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;YACxB,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC,MAAM,CAAC;YAClC,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;IACjC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B;IAClD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IACD,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;AACzB,CAAC;AAED,SAAS,QAAQ;IACf,MAAM,YAAY,GAAG,UAA0C,CAAC;IAChE,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,YAAY,CAAC,SAAS,CAAC,GAAG;YACxB,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI;YACf,iBAAiB,EAAE,KAAK;SACH,CAAC;IAC1B,CAAC;IACD,OAAO,YAAY,CAAC,SAAS,CAAgB,CAAC;AAChD,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface RemoteToolDefinition {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
inputSchema?: Record<string, unknown>;
|
|
5
|
+
outputSchema?: Record<string, unknown>;
|
|
6
|
+
annotations?: Record<string, unknown>;
|
|
7
|
+
execution?: Record<string, unknown>;
|
|
8
|
+
title?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface RemoteToolsManifest {
|
|
11
|
+
generatedAt: string;
|
|
12
|
+
serverUrl: string;
|
|
13
|
+
tools: RemoteToolDefinition[];
|
|
14
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|