preman-sdk
v0.3.0
Published
Production TypeScript SDK and CLI for turning APIs into hosted MCP servers with scoped agent tokens, audit logs, and policy controls.
Maintainers
Readme
PreMan SDK
PreMan turns REST API endpoints into hosted MCP servers that AI agents can call with scoped consumer tokens.
Use this SDK when you want to register endpoints from code or CI, deploy them as hosted MCP tools, and mint scoped tokens for agents, customers, or temporary sessions. The hosted workspace at flowtest.opentest.live is where your team sees hosted MCPs, customer tokens, audit logs, and the company knowledge graph generated from agent activity.
Your API / CI job
-> preman-sdk
-> hosted MCP URL
-> scoped token for an agent or customer
-> audit logs in the hosted workspaceInstall
npm install preman-sdkOr run the CLI directly:
npx preman-sdk init --api-key ot_live_your_keyThe CLI uses your OpenTest workspace API key. Create or copy one from OpenTest Settings. The key currently starts with ot_live_.
You can also skip init and set an environment variable:
export PREMAN_API_KEY=ot_live_your_key
# OPENTEST_API_KEY also works for compatibility with the OpenTest MCP.Quick Start
Create endpoints.json:
[
{
"method": "POST",
"path": "/auth/login",
"description": "Login with email and password.",
"scope": "auth:login",
"requestBodySchema": {
"type": "object",
"properties": {
"email": { "type": "string", "format": "email" },
"password": { "type": "string" }
},
"required": ["email", "password"]
}
}
]Register the endpoints into a Flow playground session:
npx preman-sdk register --file endpoints.json --upstream https://api.company.com--upstream is the base URL of the API PreMan should call. It is not your marketing site and it is not the hosted PreMan workspace URL.
For example, if your endpoint file contains POST /auth/login and you pass:
--upstream https://api.company.comPreMan tests and hosts the tool against:
https://api.company.com/auth/loginUse a deployed or tunneled API URL for hosted MCPs. http://localhost:8000 only works from your own machine; PreMan's hosted runtime cannot reach your laptop unless you expose it with a tunnel such as ngrok or Cloudflare Tunnel.
The CLI blocks localhost and private-network upstreams during deploy by default so you do not create a hosted MCP that cannot reach your API. Use --allow-local only for local-only previews.
Deploy the same endpoints as a hosted MCP:
npx preman-sdk deploy \
--name "Company Auth MCP" \
--file endpoints.json \
--upstream https://api.company.comMint a scoped consumer token:
npx preman-sdk token \
--mcp-id 093c4ad4-477a-4e47-94b5-24ea8f1fe4f4 \
--consumer-label "Acme support agent" \
--scopes auth:login \
--rate-limit-rpm 60Then open flowtest.opentest.live to inspect the hosted MCP, copy the install snippet, revoke tokens, and review audit logs.
TypeScript SDK
import { PremanClient } from "preman-sdk";
const preman = new PremanClient({
apiKey: process.env.PREMAN_API_KEY,
apiUrl: "https://flow.opentest.live",
appUrl: "https://www.flowtest.opentest.live",
});
const endpoints = [
{
method: "POST" as const,
path: "/auth/login",
scope: "auth:login",
description: "Login with email and password.",
requestBodySchema: {
type: "object",
properties: {
email: { type: "string", format: "email" },
password: { type: "string" },
},
required: ["email", "password"],
},
},
];
const session = await preman.registerEndpoints({
upstreamBaseUrl: "https://api.company.com",
intent: "Auth endpoints",
endpoints,
});
console.log(session.dashboardUrl);
const mcp = await preman.deployMcp({
sessionId: session.sessionId,
name: "Auth MCP",
upstreamBaseUrl: "https://api.company.com",
endpoints,
});
console.log(mcp.hostedUrl);
console.log(mcp.installSnippet?.mcpJsonString);Token Scoping
PreMan consumer tokens are scoped to a hosted MCP. The hosted MCP runtime verifies the token before forwarding a tool call to your upstream API.
A token can include:
- a hosted MCP id
- a consumer label, such as a customer or agent session
- one or more scopes, such as
auth:loginororders:write - optional rate limits
- an upstream credential binding
Calls outside the token's scope are denied by the hosted runtime and appear in the hosted workspace audit trail. Tokens can be listed, rotated, and revoked from the SDK, CLI, or hosted workspace.
preman token list --mcp-id mcp_123
preman token revoke --mcp-id mcp_123 --token-id token_123
preman token rotate --mcp-id mcp_123 --token-id token_123 --scopes auth:login --consumer-label cursor-agentImport Existing API Docs
Generate endpoint manifests from OpenAPI or Postman, then register or deploy them.
preman import openapi --file openapi.json --out endpoints.json
preman import postman --file collection.json --register --upstream https://api.company.com
preman import openapi --file openapi.json --deploy --name "Public API MCP" --upstream https://api.company.comPolicy Manifests
For CI and repeatable deploys, put the upstream, endpoints, and scopes in a manifest:
{
"name": "Auth MCP",
"upstream": "https://api.company.com",
"intent": "Auth endpoints",
"endpoints": [
{ "method": "POST", "path": "/auth/login", "scope": "auth:login" }
],
"policies": [
{ "scope": "auth:login", "rateLimitRpm": 60, "ttlSeconds": 900 }
],
"deploy": {
"name": "Auth MCP",
"initialConsumerLabel": "default-consumer"
}
}Preview before writing anything:
preman apply --file preman.config.json --dry-run
preman apply --file preman.config.json --deployGenerated Types
Create TypeScript request/response types from your endpoint manifest:
preman typegen --file endpoints.json --out preman-endpoints.tsInstall Snippets
After minting a hosted MCP consumer token, generate or write client config:
preman install-snippet \
--target cursor \
--server-name auth-mcp \
--url https://flow.opentest.live/h/mcp_123/mcp \
--token-env PREMAN_CONSUMER_TOKEN
preman install-snippet \
--target cursor \
--server-name auth-mcp \
--url https://flow.opentest.live/h/mcp_123/mcp \
--token-env PREMAN_CONSUMER_TOKEN \
--writeThe SDK also exports hostedMcpJson(), installCommand(), and writeMcpInstall() for product flows that need to generate Cursor, Claude, or VS Code instructions.
Reliability And Observability
PremanClient supports request timeouts, retries, idempotency keys, and hooks for logging.
const preman = new PremanClient({
apiKey: process.env.PREMAN_API_KEY,
timeoutMs: 15_000,
retry: { retries: 2, initialDelayMs: 250 },
hooks: {
onRequest: (event) => console.log("preman request", event.requestId, event.path),
onResponse: (event) => console.log("preman response", event.status, event.durationMs),
onError: (event) => console.error("preman error", event.status, event.error),
},
});
await preman.deployMcp({
name: "Auth MCP",
upstreamBaseUrl: "https://api.company.com",
endpoints,
request: { idempotencyKey: crypto.randomUUID() },
});For write operations that may be retried, pass an idempotency key. The client includes X-Request-Id on every request so API logs, CI logs, and hosted audit events can be correlated.
Secret Handling
Avoid putting upstream or consumer secrets in shell history. Use environment-backed secret providers:
export API_BEARER_TOKEN=prod_token
preman deploy \
--name "Auth MCP" \
--file endpoints.json \
--upstream https://api.company.com \
--upstream-secret-env API_BEARER_TOKEN \
--upstream-secret-type bearerProgrammatic helpers:
import { resolveSecret, secretFromEnv } from "preman-sdk";
const upstreamSecret = await resolveSecret(secretFromEnv("API_BEARER_TOKEN"));GitHub Action
Use the bundled action to register endpoints from CI:
name: Register endpoints
on: [push]
jobs:
preman:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Watcher1223/PreMan-Sdk@main
with:
api-key: ${{ secrets.PREMAN_API_KEY }}
endpoint-file: endpoints.json
upstream: https://api.company.comCLI Reference
npx preman-sdk init --api-key ot_live_...
npx preman-sdk status
npx preman-sdk register --file endpoints.json --upstream https://api.company.com
npx preman-sdk deploy --name "Auth MCP" --file endpoints.json --upstream https://api.company.com
npx preman-sdk token --mcp-id mcp_123 --consumer-label cursor-agent --scopes auth:login --rate-limit-rpm 60
npx preman-sdk token list --mcp-id mcp_123
npx preman-sdk token revoke --mcp-id mcp_123 --token-id token_123
npx preman-sdk import openapi --file openapi.json --out endpoints.json
npx preman-sdk apply --file preman.config.json --dry-run
npx preman-sdk typegen --file endpoints.json --out preman-endpoints.tsWhat --upstream Means
--upstream is the base URL for your real backend API:
--upstream + endpoint path = full URL PreMan callsExamples:
https://api.company.com + /auth/login = https://api.company.com/auth/login
https://staging.company.com/api + /orders = https://staging.company.com/api/ordersDo not use https://preman.live unless your actual API is hosted there. For local APIs, use a public tunnel before deploying a hosted MCP.
Configuration
The CLI stores local config at:
~/.preman/config.jsonEnvironment variables override local config:
PREMAN_API_KEY=ot_live_your_key
PREMAN_API_URL=https://flow.opentest.live
PREMAN_APP_URL=https://www.flowtest.opentest.liveCurrent API Surface
Working today:
registerEndpoints()-> creates or updates a Flow playground sessiondeployMcp()-> creates a hosted MCP from endpoint definitionscreateToken()-> mints a scoped hosted MCP consumer tokenlistTokens()/revokeToken()/rotateToken()-> manage hosted MCP token lifecycleverifyToken()/verifyBearerToken()-> verifies hosted MCP consumer tokens and scopesaudit()-> writes custom non-MCP agent events into PreMan audit logsfromOpenApi()/fromPostmanCollection()-> converts API docs into endpoint definitionspreviewManifest()/readManifest()-> validate policy-as-code manifests and dry runsgenerateEndpointTypes()-> generate TypeScript types from endpoint schemashostedMcpJson()/writeMcpInstall()-> generate or write MCP install snippetsresolveSecret()/secretFromEnv()-> keep secrets out of command text and config- framework examples for Express, Fastify, Next.js, and Hono in
examples/frameworks premanCLI -> setup, register, import, apply, deploy, tokens, typegen, install snippets, status
Hosted MCP calls are already authenticated, scoped, and audited by PreMan.
Development
npm install
npm test
npm run buildLicense
MIT
