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, import API docs or existing remote MCP servers, deploy them behind a PreMan gateway URL, and mint scoped tokens for agents, customers, or temporary sessions. The hosted workspace at app.preman.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 workspace
npm install preman-sdkOr run the CLI directly:
npx preman-sdk init --api-key pm_live_your_keyThe CLI uses your PreMan workspace API key. Create or copy one from PreMan Settings. The key currently starts with pm_live_.
You can also skip init and set an environment variable:
export PREMAN_API_KEY=pm_live_your_keyCreate 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 PreMan 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/login
Use 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 app.preman.live to inspect the hosted MCP, copy the install snippet, revoke tokens, and review audit logs.
PreMan can sit in front of APIs you discover from docs or MCP servers you already run. Agents install one PreMan URL; PreMan stores the approved tool catalog, applies auth and policy, and logs every call.
Create a hosted MCP from public API docs:
npx preman-sdk import-docs \
--url https://docs.company.com/api-reference \
--name "Company API MCP" \
--upstream https://api.company.com \
--max-endpoints 120Preview discovery without deploying:
npx preman-sdk import-docs \
--url https://docs.company.com/api-reference \
--previewPut an existing remote MCP server behind a PreMan gateway:
npx preman-sdk import-remote-mcp \
--url https://mcp.company.com/mcp \
--name "Company MCP Proxy" \
--upstream-secret-env COMPANY_MCP_TOKEN \
--auth-type header \
--auth-name Authorization \
--auth-prefix "Bearer "List the hosted MCPs in your workspace:
npx preman-sdk hosted-mcps
npx preman-sdk hosted-mcps --id mcp_123import { PremanClient } from "preman-sdk";
const preman = new PremanClient({
apiKey: process.env.PREMAN_API_KEY,
apiUrl: "https://api.preman.live",
appUrl: "https://app.preman.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);Import docs or a remote MCP directly from TypeScript:
const docsMcp = await preman.importFromDocs({
docsUrl: "https://docs.company.com/api-reference",
name: "Company API MCP",
upstreamBaseUrl: "https://api.company.com",
maxEndpoints: 120,
});
const remoteMcp = await preman.importRemoteMcp({
mcpUrl: "https://mcp.company.com/mcp",
name: "Company MCP Proxy",
initialUpstreamSecret: process.env.COMPANY_MCP_TOKEN,
upstreamAuthStyle: { type: "header", name: "Authorization", prefix: "Bearer " },
});
console.log(docsMcp.hostedUrl);
console.log(remoteMcp.installSnippet?.mcpJsonString);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-agentGenerate 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.comFor 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 --deployCreate TypeScript request/response types from your endpoint manifest:
preman typegen --file endpoints.json --out preman-endpoints.tsCreate typed wrappers from the actual hosted MCP catalog agents will call:
preman typegen --mcp-id mcp_123 --client --out preman-tools.tsThe hosted catalog typegen reads the stored tools/list schema, including nested
objects, arrays, enums, nullable fields, anyOf / oneOf, and
additionalProperties. Use --client when you want a thin typed wrapper around
your own callTool(name, args) implementation for tests or internal automations.
Pin the approved hosted MCP catalog to disk:
preman snapshot --mcp-id mcp_123 --out preman-catalog.snapshot.jsonThen fail CI if production drifts from the approved catalog:
preman diff --approved preman-catalog.snapshot.json --mcp-id mcp_123diff exits non-zero for removed tools, likely renames, broader input schemas,
or new write-capable tools (POST, PUT, PATCH, DELETE) unless you pass the
matching approval flag:
preman diff \
--approved preman-catalog.snapshot.json \
--mcp-id mcp_123 \
--allow-new-write-toolsGitHub Actions example:
name: MCP catalog drift
on:
pull_request:
push:
branches: [main]
jobs:
drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install -g preman-sdk
- run: preman diff --approved preman-catalog.snapshot.json --mcp-id ${{ vars.PREMAN_MCP_ID }}
env:
PREMAN_API_KEY: ${{ secrets.PREMAN_API_KEY }}After minting a hosted MCP consumer token, generate or write client config:
preman install-snippet \
--target cursor \
--server-name auth-mcp \
--url https://api.preman.live/h/mcp_123/mcp \
--token-env PREMAN_CONSUMER_TOKEN
preman install-snippet \
--target cursor \
--server-name auth-mcp \
--url https://api.preman.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.
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.
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"));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: PreMan-Inc/PreMan-Sdk@main
with:
api-key: ${{ secrets.PREMAN_API_KEY }}
endpoint-file: endpoints.json
upstream: https://api.company.comnpx preman-sdk init --api-key pm_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 snapshot --mcp-id mcp_123 --out preman-catalog.snapshot.json
npx preman-sdk diff --approved preman-catalog.snapshot.json --mcp-id mcp_123
npx preman-sdk typegen --file endpoints.json --out preman-endpoints.ts
npx preman-sdk typegen --mcp-id mcp_123 --client --out preman-tools.ts--upstream is the base URL for your real backend API:
--upstream + endpoint path = full URL PreMan calls
Examples:
https://api.company.com + /auth/login = https://api.company.com/auth/login
https://staging.company.com/api + /orders = https://staging.company.com/api/orders
Do not use https://preman.live unless your actual API is hosted there. For local APIs, use a public tunnel before deploying a hosted MCP.
The CLI stores local config at:
~/.preman/config.json
Environment variables override local config:
PREMAN_API_KEY=pm_live_your_key
PREMAN_API_URL=https://api.preman.live
PREMAN_APP_URL=https://app.preman.liveWorking today:
registerEndpoints()-> creates or updates a PreMan 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 schemasgenerateHostedMcpToolTypes()-> generate TypeScript types from hosted MCP tool catalogscreateCatalogSnapshot()/diffCatalogSnapshots()-> pin approved tool catalogs and detect CI drifthostedMcpJson()/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.
npm install
npm test
npm run buildMIT