No schema files to maintain

Each protocol describes itself. Bowire reads that description — gRPC Reflection, OpenAPI, GraphQL introspection, SignalR EndpointDataSource, MQTT $SYS/#, AsyncAPI — and merges the result into one sidebar.

No proto-drop folder, no curated OpenAPI mirror, no GraphQL SDL export, no hub-registration code. Add a URL, get the methods. Add a second URL, get those too. Hot-reload re-scans every few seconds so new endpoints appear without a page refresh.

Each protocol on its own dialect

Discovery isn't one mechanism polyfilled across protocols — it's the protocol's native introspection surface, used the way the spec defines it.

  • gRPCServer Reflection. Lists every service + method + message descriptor at runtime; Bowire converts that into the sidebar tree and the typed-form inputs.
  • REST / OpenAPI — reads the OpenAPI 3.x (or 2.0 Swagger) document from /swagger/v1/swagger.json or any URL you point at. Same path Swagger UI uses; nothing extra to wire.
  • GraphQL__schema introspection. Reads the type system, builds the selection-set picker, exposes subscriptions via graphql-transport-ws.
  • SignalR — ASP.NET's EndpointDataSource. Walks the registered hub mappings, enumerates typed methods, surfaces them as invokable methods + outgoing-message subscriptions.
  • MQTT — subscribes to $SYS/# for broker topology, plus a configurable topic prefix scan for application topics.
  • OData — reads the CSDL metadata document from /$metadata. Entity sets become services, bound functions and actions become callable methods.
  • AsyncAPI — parses an asyncapi.yaml / .json document (2.x + 3.0). Channels + operations become methods; the doc's bindings: route invocations through the matching wire plugin (MQTT / Kafka / WS / AMQP / HTTP).
  • Custom protocol plugins — one DiscoverAsync method on IBowireProtocol and Bowire scans the same way.
Auto-discovery feature reference →

Live, visible, plural by default

A method registered on a running server shows up in the sidebar within the next discovery tick. A URL that can't be classified surfaces an inline error rather than failing silently. Multiple --url flags? All of them.

The discovery pass repeats every few seconds against every configured URL. No page refresh, no “reconnect” dance, no manual schema re-upload. If your gRPC server adds a method while Bowire is running, the next tick adds it to the sidebar; if the GraphQL schema gets a new query field, the same.

When a URL can't be classified (no plugin claims it, the host isn't reachable, TLS cert isn't trusted), the workbench surfaces the failure inline with a clear error message and a retry button. Same path the discovery-failed screenshot in the gallery shows. No silent fall-through.

Multi-target works for the realistic case: a single Bowire instance pointed at --url grpc://users:50051 --url https://orders.example.com/openapi.json --url mqtt://broker:1883 shows all three sets of services in one sidebar, each tagged with its origin URL.

flowchart LR
    URL1(["grpc://users:50051"])
    URL2(["orders/openapi.json"])
    URL3(["mqtt://broker:1883"])
    Plugin{"Plugin
claims?"} Reflect(["gRPC Reflection"]) Parse(["OpenAPI parse"]) Subscribe(["$SYS/# subscribe"]) Sidebar[("Unified
sidebar")] Err(["Inline error + retry"]) URL1 --> Plugin URL2 --> Plugin URL3 --> Plugin Plugin -->|"gRPC"| Reflect Plugin -->|"REST"| Parse Plugin -->|"MQTT"| Subscribe Plugin -->|"unclaimed"| Err Reflect --> Sidebar Parse --> Sidebar Subscribe --> Sidebar
Each --url is classified by the matching protocol plugin and dispatched to that plugin’s native introspection mechanism. Results merge into one sidebar. Unclaimed URLs surface an inline error rather than failing silently. The same shape extends to GraphQL __schema, SignalR EndpointDataSource, OData CSDL, AsyncAPI bindings, and any third-party plugin that implements DiscoverAsync.

Point Bowire at a URL

No schema files. No registration code. The shortest path is one --url flag.

A different lane fits better? All solution lanes →