@tokenroll/htbp
v0.1.1
Published
HTBP (HTTP Tool Bridge Protocol) server SDK: expose functions as self-describing HTTP tool endpoints, FastAPI-style.
Readme
@tokenroll/htbp
HTBP (HTTP Tool Bridge Protocol) server SDK for TypeScript. Expose functions as self-describing HTTP tool endpoints, FastAPI-style. Works anywhere the fetch API does: Cloudflare Workers, Bun, Deno, and Node (via the bundled adapter).
Install
npm install @tokenroll/htbp zodzod (v4) is an optional peer dependency — used to define input schemas with
full type inference. Without zod, pass { jsonSchema, validate? } instead.
Quickstart
import { z } from 'zod';
import { Htbp } from '@tokenroll/htbp';
const app = new Htbp({ title: 'Math tools' });
app.tool(
{
name: 'add',
description: 'Add two integers.',
input: z.object({ a: z.number().int(), b: z.number().int().default(0) }),
effect: 'read',
},
({ a, b }) => a + b
);
export default app; // Cloudflare Workers / Bun / DenoNode:
import { createServer } from 'node:http';
import { toNodeListener } from '@tokenroll/htbp/node';
createServer(toNodeListener(app)).listen(8787);Every node answers GET {path}/~help (JSON by default, RFC-0001 text DSL with
Accept: text/plain); tools are invoked with POST {path} and respond with
{"resource", "result"}.
Cascading
const docs = new Htbp({ title: 'Docs tools' });
docs.tool({ name: 'search', input: z.object({ q: z.string() }) }, ({ q }) => ({ hits: [q] }));
app.mount('/docs', docs); // local nesting
app.remote('/ext', 'https://other.example.com/~help'); // federate a remote HTBP serverRemote nodes pass through ~help for any sub-path and proxy calls; the inbound
Authorization header is never forwarded upstream.
Class-based tools
import { Htbp, tool } from '@tokenroll/htbp';
class DocsTools {
@tool({ name: 'search', input: z.object({ q: z.string() }) })
search({ q }: { q: string }) {
return { hits: [q] };
}
}
app.register(new DocsTools(), { prefix: 'docs' });Options
new Htbp({
title: 'My tools',
description: '...',
auth: { bearerToken: process.env.TOKEN! }, // 401 + WWW-Authenticate without it
skill: '# Markdown served at /~skill',
basePath: '/htbp', // serve under a path prefix
cors: false, // CORS is on by default
});