Skip to content

Public executeToolCall routes MCPL tools by first matching prefix, not by listing owner / longest prefix #227

Closed

Description

@Anarchid

Found while reviewing connectome-host #191; pre-existing on main (e457abd, v0.21.0) and unchanged by #220.

What happens

executeToolCallFrom (the path behind the public executeToolCall, used for promise-based and programmatic callers) scans the server configs and takes the first whose prefix matches:

agent-framework/src/framework.ts

Lines 10905 to 10913 in e457abd

// Check if this is an MCPL-prefixed tool
const prefix = call.name.split('--').slice(0, -1).join('--');
const serverConfigs = this.mcplServerConfigs;
for (const [, config] of serverConfigs) {
const toolPrefix = config.toolPrefix ?? `mcpl--${config.id}`;
if (call.name.startsWith(toolPrefix + '--')) {
return this.executeMcplToolCall(call, config);
}
}

Model dispatch uses resolveMcplTool, which prefers the server that actually listed the tool and otherwise the longest matching prefix:

agent-framework/src/framework.ts

Lines 11956 to 11965 in e457abd

private resolveMcplTool(toolName: string): [string, string] | null {
const listedBy = this.mcplToolServers?.get(toolName);
let best: [string, string] | null = null;
for (const [prefix, serverId] of this.mcplPrefixMap ?? []) {
if (!toolName.startsWith(prefix + '--')) continue;
if (serverId === listedBy) return [serverId, prefix];
if (!best || prefix.length > best[1].length) best = [serverId, prefix];
}
return best;
}

Failure

With two servers whose prefixes nest (foo and foo--bar), a call to foo--bar--x resolves to ['inner', 'foo--bar'] on the model path, but the public path invokes server outer with tool bar--x. The same tool name runs a different server operation depending on which dispatcher it entered through. An in-memory RPC probe reproduced exactly that.

Needs nested prefixes to bite, so low frequency, but it is a wrong-target dispatch when it does.

Suggested direction

Use resolveMcplTool in executeToolCallFrom as well, and strip the resolved prefix when deriving the server-side tool name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions