Agents fall out
MCP is a host protocol over BoundOp, not a second tool DSL. Api.job promotes the ops
agents should see. Mcp.from(api) fails on duplicate tool names or non-promotable shapes.
Native protocol is 2026-07-28. HTTP and stdio also answer initialize, so Grok Build and
Cursor url / command configs work. The authoring rule is The tool is the job.
Grok → tools/list
hub ← get_show GET /shows/{id} ReadOnly
list_shows GET /shows ReadOnly
seat_the_party POST /parties
create_hold is not promoted. Catalog can still find it.Same bind the tests run. JVM, Node, or Native.
Promote, don't auto-export
JSON in and JSON out are required (OpArgs.promotable). Form, bytes, and SSE stay on HTTP.
tools/list is promoted-only. withCatalog adds search_operations and invoke so agents can
still find the rest of the Api.
tools/list (promoted only)
- get_show GET /shows/{id} ReadOnly
- list_shows GET /shows ReadOnly
- seat_the_party POST /parties
create_hold has no .mcp.Call the same function
tools/call with get_show is GET /shows/{id}. Click call on the harness above.
Point Grok Build at the hub
With sbt example/run listening:
[mcp_servers.heddle-example]
url = "http://localhost:8080/mcp"
Same Api as a local process:
[mcp_servers.heddle-example]
command = "sbt"
args = ["example/run", "--", "--mcp-stdio"]
Ask Grok to list tools, then seat a party of 2 on the Evening bill. You should see seat_the_party
and a pickup code. That is the same function Swagger just called.
stdio cold-start under sbt is slow. A packaged main is what you ship. The protocol is identical.