Loading Laminaro

Docs

One endpoint for the tools your agent needs.

Laminaro publishes a single MCP endpoint. Your agent searches the granted catalog, reads one schema at a time, and invokes the capability. Everything else — policy, approvals, secrets, rate limits and audit — happens behind that call.

https://api.uselaminaro.com/mcp/<endpoint-slug>
Setup

Quickstart

  1. 01

    Create a workspace

    Sign up, verify your address, and name the workspace your team will share. The console opens on the overview.

  2. 02

    Connect a source

    Connections hold an API description or a skill package. Paste an OpenAPI document, point at a URL, or import a skill zip. The catalog is scanned and versioned before anything is exposed.

  3. 03

    Publish an endpoint

    An endpoint is the single URL your agents call. Choose the environment and grant only the capabilities that endpoint may use. Grants are the boundary: an agent cannot reach a capability the endpoint does not hold.

  4. 04

    Create an API key

    Settings → API keys. Pick the connections the key may use, optionally narrow it to specific tools, and copy the key once. Store it in the client's secret manager, not in a prompt.

    bash
    export LAMINARO_API_KEY=sk_live_…
Clients

Connect a client

Any MCP client that speaks streamable HTTP works. Replace the slug and export the key before starting the client.

Claude Code

bash

Add the endpoint as a remote HTTP MCP server.

bash
claude mcp add --transport http laminaro \
  https://api.uselaminaro.com/mcp/<endpoint-slug> \
  --header "Authorization: Bearer $LAMINARO_API_KEY"

Claude Desktop and Cursor

json

Both read a JSON server map. Use the same URL and header.

json
{
  "mcpServers": {
    "laminaro": {
      "url": "https://api.uselaminaro.com/mcp/<endpoint-slug>",
      "headers": {
        "Authorization": "Bearer sk_live_…"
      }
    }
  }
}

Paste the key directly; these clients do not expand environment variables. Keep the file out of version control.

Vercel AI SDK

typescript

Connect with the HTTP transport, then hand the tools to any model.

typescript
import { createMCPClient } from "@ai-sdk/mcp";

const mcp = await createMCPClient({
  transport: {
    type: "http",
    url: "https://api.uselaminaro.com/mcp/<endpoint-slug>",
    headers: { Authorization: `Bearer ${process.env.LAMINARO_API_KEY}` },
  },
});

const tools = await mcp.tools();

OpenAI Agents SDK

python

Use the streamable HTTP server class with the same header.

python
import os
from agents import Agent
from agents.mcp import MCPServerStreamableHttp

async with MCPServerStreamableHttp(
    name="Laminaro",
    params={
        "url": "https://api.uselaminaro.com/mcp/<endpoint-slug>",
        "headers": {"Authorization": f"Bearer {os.environ['LAMINARO_API_KEY']}"},
    },
) as server:
    agent = Agent(name="Assistant", mcp_servers=[server])

LangChain (JS)

typescript

MultiServerMCPClient speaks Streamable HTTP; getTools() feeds the standard agent.

typescript
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createAgent } from "langchain";

const client = new MultiServerMCPClient({
  mcp: {
    transport: "http",
    url: "https://api.uselaminaro.com/mcp/<endpoint-slug>",
    headers: { Authorization: `Bearer ${process.env.LAMINARO_API_KEY}` },
  },
});

const tools = await client.getTools();
const agent = createAgent({ model: "openai:gpt-5.4", tools });

Mastra

typescript

MCPClient takes the URL and a requestInit header; listTools() returns the tool set.

typescript
import { Agent } from "@mastra/core/agent";
import { MCPClient } from "@mastra/mcp";

const mcp = new MCPClient({
  id: "laminaro",
  servers: {
    laminaro: {
      url: new URL("https://api.uselaminaro.com/mcp/<endpoint-slug>"),
      requestInit: {
        headers: { Authorization: `Bearer ${process.env.LAMINARO_API_KEY}` },
      },
    },
  },
});

const agent = new Agent({
  name: "catalog",
  instructions: "Search the catalog before invoking a capability.",
  model: "openai/gpt-5",
  tools: await mcp.listTools(),
});

Call mcp.disconnect() when the process shuts down so the transport closes cleanly.

TanStack AI

typescript

createMCPClient runs on the server; pass it to chat() and the run closes it when it ends.

typescript
// Server route or serverless function, never browser code.
import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
import { createMCPClient } from "@tanstack/ai-mcp";

export async function POST(request: Request) {
  const { messages } = await request.json();

  const mcp = await createMCPClient({
    transport: {
      type: "http",
      url: "https://api.uselaminaro.com/mcp/<endpoint-slug>",
      headers: { Authorization: `Bearer ${process.env.LAMINARO_API_KEY}` },
    },
  });

  const stream = chat({
    adapter: openaiText("gpt-5.4"),
    messages,
    mcp: { clients: [mcp] },
  });

  return toServerSentEventsResponse(stream);
}

chat() calls tools() before the first model call and closes the client on success, error and abort.

Catalog

The catalog tools

The endpoint never dumps the catalog into the context window. It exposes three tools; the agent discovers one capability at a time.

capabilities.search

Finds capabilities by intent. Returns a short list with refs, never the whole catalog.

json
{ "query": "create a customer", "limit": 5 }
capabilities.describe

Returns the full input schema for one ref. Call it before invoking so the model sees only the schema it is about to use.

json
{ "ref": "stripe.create-customer" }
capabilities.invoke

Executes the capability with the arguments its schema declared. Policy, approvals, secrets and audit all apply here.

json
{ "ref": "stripe.create-customer", "arguments": { "email": "[email protected]" } }
Ops

Operations

Auth

Every request carries Authorization: Bearer <key>. Keys are scoped to connections and optionally to individual tools; a key can never widen the endpoint's grants. Console routes refuse API keys entirely.

Rate and usage

Each endpoint has its own requests-per-minute budget. Every tools/call counts as one request against the workspace allowance. Free is 1,000 requests and 10 sandbox minutes a month; paid plans continue into $0.30 per 1,000 requests above the included amount.

Environments

An endpoint targets production, staging or a custom environment. Grants, versions and secrets resolve per environment, so a staging key cannot call a production capability.

Audit

Every invocation records the caller, the capability version, the latency, the approval and the outcome. Export the trail as CSV from Audit.

Signed skill packages

Every published skill version carries an Ed25519 signature over its checksum, tree hash, canonical manifest digest and per-file digests. Fetch the public half at POST /rpc/skills/signingKey. A grant is refused if a file, manifest or signature no longer matches; unsigned legacy versions must be republished first.

Help

Troubleshooting

401 Unauthorized

The key is missing, revoked or expired. Create a new key in Settings → API keys; the raw value is shown once.

403 Forbidden

The key is valid but not scoped to this endpoint, the browser Origin is not on the endpoint's allow-list, or your role lacks the permission.

404 Not found

The endpoint slug does not exist in an environment you belong to. Copy the URL from Endpoints rather than rebuilding it.

429 Too Many Requests

The endpoint's per-minute budget or the sandbox queue is full. Respect Retry-After instead of retrying immediately.

capabilities.invoke says the tool is unavailable

Search first, describe the exact ref, then invoke. The endpoint exposes three meta-tools, not the catalog itself.

Still stuck? Email [email protected] with the endpoint slug and the time of the call.