ob
One tool for every protocol. Execute operations across REST, gRPC, MCP, GraphQL, and more from a single command. Create interfaces from existing APIs. Generate typed clients. Serve any service as MCP tools for AI agents.
Execute anywhere
One command, any protocol. ob discovers the interface, selects a binding, dispatches.
MCP bridge
Serve any OBI as MCP tools. Claude, Cursor, and other agents connect and call operations.
Typed codegen
Point at a URL, get a typed client in TypeScript or Go. Operations become methods.
Local host
Full capability surface over HTTP with a native MCP endpoint at /mcp.
See it in action
ob ships with a built-in demo: a coffee shop exposed over six protocols simultaneously, all described by a single OpenBindings Interface.
ob demoLeave that running. In a second terminal:
# Execute an operation. ob discovers the interface, picks the best binding, makes the call.
ob op exec http://localhost:8080 getMenu
# Same operation, different protocol. Same result.
ob op exec http://localhost:8080 --binding getMenu.grpc
# Place an order over REST.
ob op exec http://localhost:8080 placeOrder \
--input '{"drink": "Schema Latte", "size": "v2", "customer": "Alice"}'
# Stream live order updates over SSE.
ob op exec http://localhost:8080 orderUpdatesOne interface. Six protocols. No protocol-specific code.
Configure demo ports:
ob demo --port 3000 --grpc-port 50051Install
brew install openbindings/tap/obOr with Go:
go install github.com/openbindings/cli/cmd/ob@latestTurn any API into MCP tools
ob mcp serves one or more OpenBindings interfaces as an MCP server. Point it at a service that publishes an OBI, a local OBI file, or any binding artifact that ob can synthesize into an OBI (an OpenAPI spec, a gRPC endpoint, etc.).
ob mcp https://api.example.comClaude Desktop, Cursor, and other MCP clients connect via stdio (default) or HTTP and see every operation as a tool. Combine multiple services into one MCP server:
ob mcp https://api.example.com https://other.example.comOperations are namespaced automatically when combining interfaces. Supports authenticated services:
ob mcp https://api.example.com --token sk-...
ob mcp https://api.example.com --token-file ./token.txtSwitch to HTTP transport for network-accessible MCP:
ob mcp http://localhost:8080 --transport http --port 9000Set a custom server name:
ob mcp http://localhost:8080 --name my-toolsGenerate typed clients
Point ob codegen at any service (a URL or a local file) and get a typed client:
ob codegen https://api.example.com --lang typescript -o ./client.tsThe generated client gives you typed methods for every operation. You choose which binding executors to include. The client calls operations; the executor handles transport.
import { OpenAPIExecutor } from "@openbindings/openapi";
import { MyServiceClient } from "./client";
const client = new MyServiceClient([new OpenAPIExecutor()]);
await client.connect("https://api.example.com", { bearerToken: "..." });
const result = await client.createWidget({ name: "foo" });
// result is typed, your editor knows the shapeFor Go:
ob codegen ./interface.json --lang go -o ./client.go --package myclientCreate from existing APIs
Already have an OpenAPI spec, AsyncAPI spec, or proto file? ob create generates an OBI from it. Your existing spec stays as-is. The OBI wraps it.
ob create openapi@3.1:./openapi.json -o interface.jsonOverride interface metadata:
ob create openapi.json --name "My Service" --version "1.0.0" --description "Public API"Serve
ob serve starts a local server that exposes ob's full capability surface. Discovery, binding execution, interface creation, context management, validation, and a native MCP endpoint, all behind a single session token.
ob serveBinds to 127.0.0.1 only. A session token is generated on startup and printed to stderr. Clients present it as Authorization: Bearer <token>.
What the server exposes:
- Discovery: OBI at
/and/.well-known/openbindings, OpenAPI spec at/openapi.yaml, AsyncAPI spec at/asyncapi.yaml - Binding execution: execute bindings via
POST /bindings/execute(supports HTTP and WebSocket) - Interface creation: create OBIs from binding sources via
POST /interfaces/create - Context management: CRUD for stored credentials and headers at
/contexts - HTTP client: make HTTP requests on behalf of callers at
POST /http/request - Authoring: validate, diff, and check compatibility via POST endpoints
- Native MCP endpoint: a full MCP server at
/mcp, exposing the same operations as tools and resources
Provide a stable token for CI/CD:
ob serve --token my-secret-token
ob serve --token-file ./token.txtConfigure CORS for browser-based clients:
ob serve --allow-origin http://localhost:3000Set a custom port (default: 20290):
ob serve --port 9000Connect as a programmatic client:
const client = new HostClient([new OpenAPIExecutor()]);
await client.connect("http://localhost:20290", { bearerToken: token });
const info = await client.getInfo();Or connect via MCP at http://localhost:20290/mcp using any MCP client.
Execute operations
ob op exec is the core command. Point it at a URL or a local file, name the operation, and ob handles the rest: discovery, binding selection, protocol dispatch, and streaming.
ob op exec http://localhost:8080 getMenuTarget a specific binding:
ob op exec http://localhost:8080 --binding getMenu.grpcPass input as JSON:
ob op exec http://localhost:8080 placeOrder \
--input '{"drink": "Schema Latte", "size": "v2", "customer": "Alice"}'Streaming operations output one JSON value per line until the stream closes:
ob op exec http://localhost:8080 orderUpdatesWorks with local files:
ob op exec ./my-service.obi.json getMenuUse --verbose to see which binding was selected and how long execution took:
ob op exec http://localhost:8080 getMenu -vDiscover and fetch
Download a service's OBI for local inspection or offline use:
ob fetch localhost:8080Tries the URL directly, then falls back to /.well-known/openbindings, and writes the result to a local file.
Manage credentials
ob context stores credentials and headers per service URL. These are used automatically when executing operations. Credentials are stored in the OS keychain. Non-secret fields (headers, cookies, environment) go to config files.
ob context set https://api.example.com --bearer-token sk-...
ob context set https://api.example.com --api-key my-key
ob context set https://api.example.com --header "X-Custom: value"
ob context set https://api.example.com --cookie "session=abc123"
ob context set https://internal.example.com --basic # prompts for username/passwordImport context from a curl command:
ob context set https://api.example.com --from-curl 'curl -H "Authorization: Bearer sk-..." https://api.example.com'Scope credentials to a specific source within an interface:
ob context set https://api.example.com --source adminApi --bearer-token sk-admin-...Pass environment variables for CLI-based binding executors:
ob context set https://api.example.com --env "API_ENV=production"ob context list # show all stored contexts
ob context get <url> # show details for a URL (secrets masked)
ob context remove <url> # delete a contextValidate and compare
Check structural correctness and role conformance:
ob validate my-service.obi.json✓ Valid
Role Conformance
✓ openbindings.context-store -- 4/4 operations
✓ openbindings.software-descriptor -- 1/1 operationsUse --skip-roles to disable conformance checking. Use --strict to additionally reject unknown fields and require a supported version.
Compare two interfaces for compatibility:
ob compat published-interface.json my-service.obi.jsonThe first argument is the target, the second is the candidate. Checks operation matching (by key, alias, or satisfies declaration) and schema compatibility (input/output directional rules per the spec).
Structural diff between two OBIs:
ob diff baseline.json updated.jsonOr compare an OBI against what its binding sources currently produce:
ob diff my-service.obi.json --from-sourcesSync and merge
Re-read binding sources and merge changes into your OBI:
ob sync my-service.obi.jsonSync preserves local edits with a three-way merge. Use --force to prefer source for all conflicts. Scope to specific operations with --op:
ob sync my-service.obi.json --op getUser --op listUsersSelectively apply changes from one OBI into another:
ob merge target.obi.json source.obi.jsonOr derive changes from the target's own binding sources:
ob merge target.obi.json --from-sourcesPreview first with --dry-run, or apply everything with --all.
List merge conflicts between local edits and source changes:
ob conflicts my-service.obi.jsonManage sources
Add, list, and remove binding source references on an OBI:
ob source add my-service.obi.json openapi@3.1:./openapi.json
ob source list my-service.obi.json
ob source remove my-service.obi.json publicApi