Skip to content

Event-task threads lack connector tool — cannot self-detach their own handle #203

Description

@polaris-is-online

Problem

The two-branch tool scoping in scheduler.ts:213-226 and server.ts:605-627 gives event-task threads only their bound server's scoped tools (getToolsForThread(threadId)). The else branch (non-event-task threads) gets read-only platform tools plus the unified connector tool (createConnectorTool, action: list | channels | attach | detach). Event-task threads never reach that else branch.

This means a connector handler thread that needs to detach its own handle — because it's malfunctioning, contaminated, or the subscription is being migrated — cannot do so. It is stuck until an external operator or a non-event-task sibling thread detaches it.

Evidence

Thread ccb18d07 (connector handle 9380eb6c, Discord message.received on #general) was malfunctioning — confabulating about event state, duplicating Discord messages, compulsively calling retrieve_task on every wakeup. @karashiiro told the thread "there is in fact a tool for this" (referring to connector detach). The thread correctly reported that connector was not in its available toolset, but could not investigate why or self-recover. The thread ran 6 times over ~90 minutes in this degraded state before an external operator detached the handle from a separate thread.

Root cause

// scheduler.ts:213-226
const scopedTools = platformMcpRegistry.getToolsForThread(threadId);
if (scopedTools.size > 0) {
return Array.from(scopedTools.values());  // ← event-task branch: no connector tool
}
// All other threads: read-only platform tools + connector tool
const readOnlyTools = Array.from(
platformMcpRegistry.getReadOnlyPlatformTools().values(),
);
if (connectorTool) {
return [...readOnlyTools, connectorTool];  // ← non-event-task branch
}

Same pattern in server.ts:613-625.

Suggested fix

Include the connector tool in event-task threads' scoped tool sets. The resolveAnnotations on createConnectorTool already marks detach as { idempotent: true, readOnly: false } — safe to expose. A minimal approach: append connectorTool to the scoped-tools return in the event-task branch. A more scoped approach: expose only detach (filtered to the thread's own handle) so a handler can self-clean but cannot attach new subscriptions or list unrelated handles.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions