mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:30:57 +00:00
fix(mcp): honor plugin tool policy
This commit is contained in:
@@ -52,6 +52,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Gateway/sessions: memoize repeated thinking-option enrichment and skip unused cost fallback checks while listing sessions, reducing per-row work on large multi-agent stores. Fixes #76931.
|
||||
- Agents/tools: use config-only runtime snapshots for plugin tool registration and live runtime config getters, avoiding expensive full secrets snapshot clones on the core-plugin-tools prep path. Fixes #76295.
|
||||
- Agents/tools: honor the effective tool denylist before constructing optional PDF/media tool factories, so `tools.deny: ["pdf"]` skips PDF setup before later policy filtering. Fixes #76997.
|
||||
- MCP/plugin tools: apply global `tools.profile`, `tools.alsoAllow`, and `tools.deny` policy while exposing plugin tools over the standalone MCP bridge, so ACP clients do not see policy-hidden plugin tools or miss opt-in optional tools. Thanks @vincentkoc.
|
||||
- Plugin tools: honor explicit tool denylists while selecting plugin tool runtimes, so denied plugin tools are not materialized for direct command or gateway surfaces before later policy filtering. Thanks @vincentkoc.
|
||||
- Agents/bootstrap: keep pending `BOOTSTRAP.md` and bootstrap truncation notices in system-prompt Project Context instead of copying setup text or raw warning diagnostics into WebChat user/runtime context. Fixes #76946.
|
||||
- Channels/WhatsApp: allow `@whiskeysockets/libsignal-node` in `onlyBuiltDependencies` so pnpm v9+ `blockExoticSubdeps` no longer rejects the baileys git-tarball subdep and silences all inbound agent replies. Fixes #76539. Thanks @ottodeng and @vincentkoc.
|
||||
|
||||
@@ -87,6 +87,32 @@ describe("plugin tools MCP server", () => {
|
||||
expect(connectToolsMcpServerToStdioMock).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("threads global plugin tool policy into plugin resolution", async () => {
|
||||
getRuntimeConfigMock.mockReturnValueOnce({
|
||||
plugins: { enabled: true },
|
||||
tools: {
|
||||
alsoAllow: ["memory_search"],
|
||||
deny: ["memory_forget"],
|
||||
},
|
||||
} as never);
|
||||
const { servePluginToolsMcp } = await import("./plugin-tools-serve.js");
|
||||
|
||||
await servePluginToolsMcp();
|
||||
|
||||
expect(ensureStandalonePluginToolRegistryLoadedMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
toolAllowlist: expect.arrayContaining(["memory_search"]),
|
||||
toolDenylist: ["memory_forget"],
|
||||
}),
|
||||
);
|
||||
expect(resolvePluginToolsMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
toolAllowlist: expect.arrayContaining(["memory_search"]),
|
||||
toolDenylist: ["memory_forget"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("lists registered plugin tools and serializes non-array tool content", async () => {
|
||||
const execute = vi.fn().mockResolvedValue({
|
||||
content: "Stored.",
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
*/
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { pickSandboxToolPolicy } from "../agents/sandbox-tool-policy.js";
|
||||
import {
|
||||
collectExplicitAllowlist,
|
||||
collectExplicitDenylist,
|
||||
mergeAlsoAllowPolicy,
|
||||
resolveToolProfilePolicy,
|
||||
} from "../agents/tool-policy.js";
|
||||
import type { AnyAgentTool } from "../agents/tools/common.js";
|
||||
import { getRuntimeConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
@@ -16,12 +23,32 @@ import { routeLogsToStderr } from "../logging/console.js";
|
||||
import { ensureStandalonePluginToolRegistryLoaded, resolvePluginTools } from "../plugins/tools.js";
|
||||
import { connectToolsMcpServerToStdio, createToolsMcpServer } from "./tools-stdio-server.js";
|
||||
|
||||
function resolvePluginToolPolicy(config: OpenClawConfig): {
|
||||
toolAllowlist?: string[];
|
||||
toolDenylist?: string[];
|
||||
} {
|
||||
const profilePolicy = mergeAlsoAllowPolicy(
|
||||
resolveToolProfilePolicy(config.tools?.profile),
|
||||
config.tools?.alsoAllow,
|
||||
);
|
||||
const globalPolicy = pickSandboxToolPolicy(config.tools);
|
||||
const toolAllowlist = collectExplicitAllowlist([profilePolicy, globalPolicy]);
|
||||
const toolDenylist = collectExplicitDenylist([profilePolicy, globalPolicy]);
|
||||
return {
|
||||
...(toolAllowlist.length > 0 ? { toolAllowlist } : {}),
|
||||
...(toolDenylist.length > 0 ? { toolDenylist } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
function resolveTools(config: OpenClawConfig): AnyAgentTool[] {
|
||||
const pluginToolPolicy = resolvePluginToolPolicy(config);
|
||||
ensureStandalonePluginToolRegistryLoaded({
|
||||
context: { config },
|
||||
...pluginToolPolicy,
|
||||
});
|
||||
return resolvePluginTools({
|
||||
context: { config },
|
||||
...pluginToolPolicy,
|
||||
suppressNameConflicts: true,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user