Skip to content

Proposal: Stream Tool Arguments #82

Open

Description

@MiguelsPizza

Currently, execute fires after the full args JSON is parsed. For tools with large text args (email bodies, code), it'd be nice to stream chunks into page UI as the model generates them. example from userland

navigator.modelContext.registerTool({
  name: "compose_email",
  stream: true,
  inputSchema: { /* to, subject, body */ },
  execute: async (call) => {
    composer.open();
    for await (const { key, chunk } of call) {
      if (key === "to")   composer.appendTo(chunk);
      if (key === "body") composer.appendBody(chunk);
    }
    const { to, subject, body } = await call.args;
    return { content: [{ type: "text", text: `Draft created` }] };
  }
});

For declarative tools this could be default behavior.

Activity

  1. MiguelsPizza commented on Mar 9, 2026

    @MiguelsPizza
    ContributorAuthor

    Here's a streaming demo running in a local Chromium fork with the proposed API:

    WebMCP.stream.demo.mp4
    navigator.modelContext.registerTool({
        name: 'compose_site',                                                                                                                
        description: 'Stream HTML progressively into a live preview.',                                                                       
        stream: true,                                                                                                                        
        inputSchema: {                                                                                                                       
          type: 'object',                                                                                                                    
          properties: { html: { type: 'string' } },                   
          required: ['html'],
        },
        async execute(call) {
          for await (const { key, chunk } of call) {                                                                                         
            if (key === 'html') {
              htmlBuffer += chunk;                                                                                                           
              preview.innerHTML = htmlBuffer;                         
            }
          }                                                                                                                                  
       
          const { html } = await call.args;                                                                                                  
          preview.innerHTML = html;                                   
          return { content: [{ type: 'text', text: 'Site composed.' }] };                                                                    
        },                                                                                                                                   
      });

    I think this API would be a great way to show off what you can make with WebMCP and how it is different from MCP.

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

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions