npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@authlane/ai

v0.1.0

Published

Local AI framework adapters for Authlane user-scoped tools

Readme

@authlane/ai

Framework adapters that turn one Authlane user's connected-service definitions into locally executable AI tools. Authlane remains the credential and capability control plane; provider calls originate in your SaaS process.

How execution works

  1. Authenticate a user in your SaaS backend and derive their externalUserId from that trusted session.
  2. Create authlane.user(externalUserId) and list tools with a framework adapter.
  3. Pass the returned toolset directly to the framework in the same server request or user-bound runtime.
  4. When the framework invokes a generated callback, the SDK requests one fresh, audited, access-only credential lease and runs the matching integration locally.
  5. The integration calls the provider directly. Authlane never receives the provider request or response.

The initial tool listing is a control-plane capability read. It does not issue a credential lease.

Vercel AI SDK

ai is an optional peer, so install it explicitly with the SDK and adapter package:

pnpm add @authlane/sdk @authlane/ai ai zod
import { vercelAI } from '@authlane/ai/vercel';
import { Authlane } from '@authlane/sdk';
import { createTextStreamResponse, streamText, toTextStream } from 'ai';

const authlane = new Authlane({
  apiKey: process.env.AUTHLANE_API_KEY!,
  baseUrl: 'https://app.authlane.io',
});

const currentUser = await requireUser(request);
const user = authlane.user(currentUser.id);
const { data: tools, error } = await user.tools.list({ adapter: vercelAI() });

if (error) {
  return Response.json(
    { error: { code: error.code, message: error.message } },
    { status: error.statusCode ?? 400 },
  );
}

const result = streamText({
  model: 'openai/gpt-5-mini',
  messages,
  tools,
});

return createTextStreamResponse({
  stream: toTextStream({ stream: result.stream }),
});

OpenAI Agents SDK

@openai/agents is an optional peer, so install it explicitly:

pnpm add @authlane/sdk @authlane/ai @openai/agents zod
import { openAIAgents } from '@authlane/ai/openai';
import { Authlane } from '@authlane/sdk';
import { Agent, run } from '@openai/agents';

const authlane = new Authlane({
  apiKey: process.env.AUTHLANE_API_KEY!,
  baseUrl: 'https://app.authlane.io',
});
const currentUser = await requireUser(request);
const { data: tools, error } = await authlane
  .user(currentUser.id)
  .tools.list({ adapter: openAIAgents() });

if (error) {
  return Response.json(
    { error: { code: error.code, message: error.message } },
    { status: error.statusCode ?? 400 },
  );
}

const agent = new Agent({
  name: 'Workspace assistant',
  instructions: 'Use connected services only when needed.',
  tools,
});
const result = await run(agent, prompt);

return Response.json({ output: result.finalOutput });

Mastra

@mastra/core is an optional peer. Install it only in applications that use the Mastra adapter:

pnpm add @authlane/sdk @authlane/ai @mastra/core zod
import { mastraAI } from '@authlane/ai/mastra';
import { Authlane } from '@authlane/sdk';
import { Agent } from '@mastra/core/agent';

const authlane = new Authlane({
  apiKey: process.env.AUTHLANE_API_KEY!,
  baseUrl: 'https://app.authlane.io',
});
const currentUser = await requireUser(request);
const { data: tools, error } = await authlane
  .user(currentUser.id)
  .tools.list({ adapter: mastraAI() });

if (error) {
  return Response.json(
    { error: { code: error.code, message: error.message } },
    { status: error.statusCode ?? 400 },
  );
}

const agent = new Agent({
  id: 'workspace-assistant',
  name: 'Workspace assistant',
  instructions: 'Use connected services only when needed.',
  model: 'openai/gpt-5-mini',
  tools,
});

return Response.json({ output: await agent.generate(prompt) });

The returned object contains Mastra-native tools with JSON Schema input validation. Each tool is bound to the authenticated external user and delegates provider work through the same fresh, audited credential-lease path as the other adapters.

Local MCP with a caller-owned transport

@modelcontextprotocol/sdk is an optional peer, so install it explicitly:

pnpm add @authlane/sdk @authlane/ai @modelcontextprotocol/sdk zod

mcpServer() builds an MCP Server. Authlane does not host it and does not choose the transport; your application owns the transport and server lifecycle.

import { mcpServer } from '@authlane/ai/mcp';
import { Authlane } from '@authlane/sdk';
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';

const authlane = new Authlane({
  apiKey: process.env.AUTHLANE_API_KEY!,
  baseUrl: 'https://app.authlane.io',
});

export async function connectUserMcpServer(
  authenticatedExternalUserId: string,
  transport: Transport,
) {
  const result = await authlane
    .user(authenticatedExternalUserId)
    .tools.list({ adapter: mcpServer() });

  if (result.error) return result;
  await result.data.connect(transport);
  return result;
}

One returned MCP server is permanently bound to one authenticated external user. Never reuse a server or its transport for another identity, tenant, browser session, or concurrent shared user context. Close both when that user-bound lifecycle ends.

Custom integration override

Every adapter accepts FrameworkAdapterOptions.integrations. An explicit custom adapter wins over the built-in adapter with the same serviceId:

import type { FrameworkAdapterOptions } from '@authlane/ai';
import { vercelAI } from '@authlane/ai/vercel';

type IntegrationAdapter = NonNullable<FrameworkAdapterOptions['integrations']>[number];

const customGithub: IntegrationAdapter = {
  serviceId: 'github',
  definitions: [],
  async execute(toolName, input, credential) {
    return executeGithubInsideOurBackend(toolName, input, credential);
  },
};

const { data: tools, error } = await authlane.user(currentUser.id).tools.list({
  adapter: vercelAI({ integrations: [customGithub] }),
});

The capability snapshot still decides which tools the user may call. The override changes only the local handler for that service. Custom handlers execute inside your SaaS trust boundary and must validate input and constrain outbound requests.

Errors and security

  • Create user scopes only from a server-authenticated tenant user. Never take externalUserId from a model, tool arguments, URL parameter, or untrusted browser body.
  • Keep the tenant Authlane API key server-only.
  • Never serialize executable toolsets or MCP servers to a browser, log them, or cache them across identities.
  • The SDK requests a fresh access-only lease for each allowed invocation. Retain it only within that invocation; never log, persist, cache, return, or reuse it.
  • OAuth refresh tokens and ID tokens never leave Authlane.
  • Adapter and model-facing failures are fixed safe code/message values. Caught provider errors, response bodies, credential values, and stack traces are not forwarded.
  • Provider traffic goes directly from the SaaS process to the provider. Authlane has no hosted tool-execution endpoint, gateway, or MCP server.

All Authlane SDK calls use the non-throwing { data, error } contract for expected API and adapter failures. Framework or transport lifecycle calls may still throw according to their own public contracts; handle them at your application's trust boundary.