Model Context Protocol is not enough

Model Context Protocol defines remote procedure calls for AI tools. It has input schemas but no output schemas. Tool responses return an untyped content array. Input gets validated. Output does not.

This breaks algebra. A model calls a tool and gets everything back as untyped content. Servers often return human-readable text instead of structured data to improve model performance, but this prevents composition entirely. Models cannot map, filter, or chain operations.

Worse, all that untyped content fills context windows. Models process dozens of fields they do not need, burning context on data they cannot use algebraically. With proper output schemas and operators, models could project just the fields they need and compose operations. Instead they get everything, process everything, and still cannot compose.

OpenAPI already solved this

Most APIs do not implement MCP. They implement HTTP with an OpenAPI specification. OpenAPI defines input schemas, output schemas, error responses. Nearly the entire web uses it.

Nushell is a shell with structured data pipelines. Commands output typed tables, lists, and records instead of text. The shell provides algebraic operators: where for filtering, select for projection, each for mapping. These operators compose because data is structured.

I am building a Nushell plugin that generates typed commands from any specification format. The plugin transforms OpenAPI specifications, gRPC service definitions via reflection, and JSON-RPC schemas into typed Nushell commands. Nushell’s algebraic operators work across all of them:

linear issues --status "In Progress" --assignee me
  | where priority == "high"
  | par-each { |issue|
      linear comments --issue $issue.id
      | length
    }
  | wrap comment_count

The pipeline filters, then maps in parallel. Types validate at runtime. Help documentation generates from the spec:

 linear issues --help
List and filter issues from Linear.

Flags:
  -s, --status <string>: Filter by status
  -a, --assignee <string>: Filter by assignee

Input/output types:
  ╭─#─┬──input──┬────────output────────╮
 0 nothing table<id, title...>
  ╰─#─┴──input──┴────────output────────╯

Future work

The missing piece is OAuth. Nushell needs a standard way to provide OAuth tokens safely to generated commands. Solve that and anyone can generate typed, composable commands for any API with a specification format.

I am building this as open source Nushell plugins for Superglide, my AI editor. If you are interested in contributing or want to discuss this, check out the GitHub or join our Discord.