Skip to content

WebMCP tool execution progress report #196

@beaufortfrancois

Description

@beaufortfrancois

Introduction & Objectives

As Language Models and Agentic workflows become deeply integrated into the web platform via WebMCP, some tools registered by web applications may be tasked with long-running operations (e.g., repository indexing, complex multi-file analyses). Currently, the ToolExecuteCallback interface executes asynchronously but behaves as a "black box" until the final promise resolves or rejects. There is no native mechanism for an active tool execution to stream intermediate telemetry, status messages, or sub-task heartbeats back to the calling agent, which leaves both the agent and the user without visibility into the tool's current state.

Better agent to agent integrations

A common agentic pattern is to expose sub-agents to a coordinator as tools. This pattern also enables websites to expose their own agents to browser agents. Similar to other tasks described in this document, invoking a sub-agent can be a long running process. The progress report feature would enable sub-agents to send progress updates: thinking blocks, partial texts, and details on their own tool calls to the browser agent, so it can display their content to the user.

Note

While it’s up to the agent to decide how to use the progress reports it receives, the goal is to use the information to show progress of the tool call to the user, and the content of those reports should not be included in the conversation between agents, to avoid context bloat.

Proposed API changes

partial interface ModelContextClient {
    undefined reportProgress(DOMString message);
};

interface ToolProgressEvent : Event {
    constructor(DOMString type, optional ToolProgressEventInit eventInitDict = {});
    readonly attribute DOMString toolName;
    readonly attribute DOMString message;
};

dictionary ToolProgressEventInit : EventInit {
    DOMString toolName = "";
    DOMString message = "";
};

partial interface ModelContext : EventTarget {
    attribute EventHandler ontoolprogress;
};

JavaScript example

// 1. Tool Implementation with Progress Updates
async function* runTasks() {
  yield { type: 'thinking', text: 'Analyzing your workspace...' };
  await new Promise((r) => setTimeout(r, 800));

  yield { type: 'tool_start', name: 'hackathon-analyzer', params: { file: 'reasons.md' } };
  await new Promise((r) => setTimeout(r, 1200));

  yield { type: 'tool_finish', name: 'hackathon-analyzer' };
  await new Promise((r) => setTimeout(r, 500));

  yield { type: 'text', text: 'Analysis complete! Found 3 migration reasons.' };
}

// 2. Registering the Tool with the injected client
document.modelContext.registerTool({
  name: 'workspace-analyzer',
  description: 'Analyzes files in the current workspace directory',
  execute: async (input, client) => {
    for await (const message of runTasks()) {
      // Serialize updates to string data
      client.reportProgress(JSON.stringify(message));
    }
    return { success: true };
  },
});

// 3. Orchestrator observing runtime progress hooks
document.modelContext.ontoolprogress = (event) => {
  const { toolName, message } = event;
  const data = JSON.parse(message);
  
  console.log(`[Progress Update] Tool: ${toolName}`, data);
};

Resources

Open questions

A key challenge remains: determining how an extension can effectively track concurrent tool executions. Tool execution IDs are currently unavailable until executeTool() completes, which complicates parallel monitoring. Shall we introduce a new monitor object in ExecuteToolOptions instead of document.modelContext.ontoolprogress to report progress?

const result = await document.modelContext.executeTool(myTool, {
  monitor(m) {
    m.addEventListener('progress', ({ message }) => {
      // Report progress to the extension sidebar
      chrome.runtime.sendMessage({
        toolExecutionId: m.toolExecutionId,
        toolName: m.toolName,
        message,
      });
    });
  },
});
// Report final result from tool execution.
chrome.runtime.sendMessage({ result });

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions