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

intentkit

v5.0.0

Published

The agent-native framework. Define intent, not routes.

Readme

CI npm version License: MIT Node.js

IntentKit

The agent-native framework. Define intent, not routes.

IntentKit is a TypeScript framework for building services that AI agents consume directly via MCP. No REST controllers. No middleware chains. No frontend. Just functions with intent, typed schemas, and direct database access.

  • Three primitivesdefineFunction(), defineTrigger(), defineGoal()
  • Capability-based permissions — agents without access never see the function (invisible deny, not 403)
  • Event busctx.emit() decouples side effects from business logic
  • 31 adapter packages — service adapters, macOS automation, agent bridges, observability
  • Agent-to-agent — identity, discovery, trust, negotiation, service mesh
  • Agent economy — function pricing, wallets, escrow, marketplace
  • SQLite + PostgreSQL — direct ctx.db access with transactions, no ORM
  • 6 project templatesnpx intentkit init my-api --template saas-api
import { defineFunction, z } from 'intentkit';

export const createTask = defineFunction({
  name: 'create_task',
  intent: 'Create a new task with a title and priority level',
  permissions: ['task:create'],

  input: z.object({
    title: z.string(),
    priority: z.enum(['low', 'medium', 'high']).optional(),
  }),

  output: z.object({
    id: z.number(),
    message: z.string(),
  }),

  execute: async (input, ctx) => {
    const { lastInsertRowid } = await ctx.db.run(
      `INSERT INTO tasks (title, priority) VALUES (?, ?)`,
      [input.title, input.priority ?? 'medium'],
    );
    await ctx.emit('task.created', { id: Number(lastInsertRowid), title: input.title });
    return { id: Number(lastInsertRowid), message: `Task "${input.title}" created` };
  },
});

One function. Intent for agents. Schema for validation. Permissions for access control. Events for side effects. Direct database access. No ceremony.


Who is this for?

  • Backend developers building services that AI agents consume via MCP
  • Teams adding an agent layer to existing Express/NestJS/Fastify apps (sidecar pattern)
  • Developers who want conventions without ceremony — structure and opinions, not boilerplate
  • Anyone building for the agent economy — Claude Desktop, Dispatch, OpenClaw, custom agents

Architecture

graph LR
  Agent["AI Agent<br/>(Claude, OpenClaw, custom)"] -->|MCP / REST / OpenAI| Server["IntentKit<br/>serve()"]
  Server --> Registry["Registry<br/>defineFunction()"]
  Server --> Triggers["Triggers<br/>defineTrigger()"]
  Server --> Goals["Goals<br/>defineGoal()"]
  Registry --> Functions["Your Functions"]
  Functions --> DB["Database<br/>ctx.db"]
  Functions --> Providers["Adapters<br/>ctx.providers"]
  Functions --> Events["Event Bus<br/>ctx.emit()"]
  Server --> Discovery["Discovery<br/>AgentIdentity"]
  Server --> Economy["Economy<br/>AgentWallet"]

The MCP SDK handles the protocol. IntentKit handles the architecture. Adapters handle service connections. They compose — they don't compete.


Quick Start

Option 1: Scaffold from template

npx intentkit init my-api --template saas-api
cd my-api
npm install
npm run seed
npx intentkit dev src/serve.ts --watch

Available templates: saas-api, customer-support, internal-tools, data-pipeline, devops-bot, personal-assistant

Option 2: Scaffold a blank project

npx intentkit init my-api
cd my-api
npm install
npm run seed
npx intentkit dev src/serve.ts --watch

Option 3: Add to existing project

npm install intentkit

Core API

defineFunction() — The Foundation

import { defineFunction, z } from 'intentkit';

export const myFunction = defineFunction({
  name: 'do_something',           // MCP tool name
  intent: 'What this does...',    // Agents read this to decide to call it
  permissions: ['resource:action'], // Required capabilities
  requires: ['mail'],             // Provider dependencies (validated at startup)
  cost: { amount: 0.5, currency: 'credits' }, // Optional pricing (v5.0)

  input: z.object({ /* ... */ }),  // Zod schema — validates + documents
  output: z.object({ /* ... */ }), // What agents get back

  execute: async (input, ctx) => {
    // ctx.db         — direct database access
    // ctx.log        — structured logger
    // ctx.caller     — who's calling (role, capabilities)
    // ctx.emit       — fire events for side effects
    // ctx.providers  — adapter instances (mail, cache, etc.)
    // ctx.meta       — mutable request-scoped data (shared between hooks)
    // ctx.requestId  — unique UUID per MCP tool call
    return { /* ... */ };
  },
});

defineTrigger() — Proactive Agents (v2.0)

import { defineTrigger } from 'intentkit';

export const followUpTrigger = defineTrigger({
  name: 'overdue_follow_up',
  intent: 'When an overdue invoice email arrives, block calendar time for follow-up',
  condition: {
    watcher: 'email',
    filter: { unread: true },
    and: [
      { check: 'list_invoices', input: (email) => ({ client: email.from, status: 'overdue' }), expect: { count: { gte: 1 } } },
    ],
  },
  action: {
    call: 'create_event',
    input: (email) => ({ title: `Follow up: ${email.subject}`, duration: 60, date: 'tomorrow' }),
  },
  cooldown: { intervalSeconds: 3600, maxPerHour: 3 },
});

defineGoal() — Persistent Objectives (v4.0)

import { defineGoal } from 'intentkit';

export const inboxZero = defineGoal({
  name: 'inbox_zero',
  intent: 'Process all unread emails down to zero',
  metrics: [
    { name: 'unread_count', check: 'check_mail', input: { unreadOnly: true }, target: 0, operator: 'eq' },
  ],
  timeHorizon: { hours: 24 },
  triggers: ['overdue_follow_up'],
  functions: ['search_mail', 'create_reminder'],
});

IntentRegistry — The Catalog

import { IntentRegistry } from 'intentkit';

const registry = new IntentRegistry()
  .register(createTask, moveTask, listTasks, deleteTask);

// Merge multiple registries
const combined = IntentRegistry.merge(taskRegistry, orderRegistry);

serve() — MCP Server with Everything

import { serve } from 'intentkit';

await serve({
  name: 'my-service',
  version: '1.0.0',
  registry,
  context,
  providers: [createMailProvider({ ... })],
  triggers: triggerRegistry,          // Proactive agents (v2.0)
  identity: createIdentity(),         // Agent-to-agent (v3.0)
  discovery: new InMemoryDiscovery(), // Service discovery (v3.0)
  transport: 'stdio',                 // or 'http'
  roles: {
    admin:  ['*'],
    member: ['task:read', 'task:create', 'task:update'],
    viewer: ['task:read'],
  },
  defaultRole: 'member',
});

Context API

Every function receives ctx with:

| Property | Type | Description | |----------|------|-------------| | ctx.db.run(sql, params) | { changes, lastInsertRowid } | Execute INSERT/UPDATE/DELETE | | ctx.db.get(sql, params) | T \| undefined | Get one row | | ctx.db.all(sql, params) | T[] | Get all matching rows | | ctx.db.transaction(fn) | T | Atomic operations with automatic rollback on error | | ctx.log.info/warn/error | void | Structured logging (JSON or pretty format) | | ctx.caller | CallerIdentity | Role + capabilities of the caller | | ctx.emit(name, data) | Promise<void> | Fire an event | | ctx.meta | Record<string, unknown> | Mutable request-scoped data shared between hooks | | ctx.providers | Record<string, unknown> | Named adapter instances (e.g., ctx.providers.mail) | | ctx.requestId | string | Unique UUID per MCP tool call |


Permissions

IntentKit uses capability-based access control that's fundamentally different from REST:

In REST: an agent tries to call an endpoint -> gets 403 -> already knew the endpoint existed.

In IntentKit: an agent without permission never sees the function at all. Invisible deny.

// The function declares what it needs
export const deleteTask = defineFunction({
  permissions: ['task:delete'],
  // ...
});

// Roles define what agents have
roles: {
  admin:  ['task:*'],     // wildcard — all task operations
  member: ['task:read'],  // can't see delete_task
}

Wildcard matching: task:* matches any task action. *:read matches read on any resource. * matches everything.


Adapters & Providers

IntentKit stays lean — adapters handle external service connections as separate packages.

Service Adapters

| Adapter | Description | Install | |---------|-------------|---------| | intentkit-http | Generic HTTP/REST client | npm i intentkit-http | | intentkit-mail | IMAP reading + SMTP sending | npm i intentkit-mail | | intentkit-cache | Redis caching via ioredis | npm i intentkit-cache | | intentkit-queue | BullMQ job queue | npm i intentkit-queue | | intentkit-storage | S3-compatible file storage | npm i intentkit-storage | | intentkit-auth | JWT signing/verification | npm i intentkit-auth | | intentkit-calendar | CalDAV calendar access | npm i intentkit-calendar | | intentkit-slack | Slack messaging | npm i intentkit-slack |

Agent Bridges

| Adapter | Description | Install | |---------|-------------|---------| | intentkit-rest | REST API bridge (non-MCP consumers) | npm i intentkit-rest | | intentkit-openai | OpenAI function calling format | npm i intentkit-openai | | intentkit-openclaw | OpenClaw skills generator | npm i intentkit-openclaw | | intentkit-graphql | GraphQL bridge | npm i intentkit-graphql | | intentkit-websocket | WebSocket bridge | npm i intentkit-websocket |

Observability

| Adapter | Description | Install | |---------|-------------|---------| | intentkit-observe | Telemetry middleware | npm i intentkit-observe | | intentkit-dashboard | Web UI for telemetry | npm i intentkit-dashboard | | intentkit-otel | OpenTelemetry exporter | npm i intentkit-otel | | intentkit-audit | Immutable audit log | npm i intentkit-audit | | intentkit-studio | Interactive function testing UI | npm i intentkit-studio |

macOS Automation

| Adapter | Description | Install | |---------|-------------|---------| | intentkit-macos-core | Shared JXA runner | npm i intentkit-macos-core | | intentkit-macos-mail | Mail.app automation | npm i intentkit-macos-mail | | intentkit-macos-calendar | Calendar.app automation | npm i intentkit-macos-calendar | | intentkit-macos-fs | File system + Spotlight | npm i intentkit-macos-fs | | intentkit-macos-notes | Notes.app automation | npm i intentkit-macos-notes | | intentkit-macos-reminders | Reminders.app automation | npm i intentkit-macos-reminders | | intentkit-macos-shell | Safe shell execution | npm i intentkit-macos-shell | | intentkit-macos-browser | Safari automation | npm i intentkit-macos-browser | | intentkit-macos-system | System controls | npm i intentkit-macos-system | | intentkit-macos-notify | Native notifications | npm i intentkit-macos-notify | | intentkit-macos-search | Spotlight search | npm i intentkit-macos-search | | intentkit-macos-contacts | Contacts.app automation | npm i intentkit-macos-contacts | | intentkit-macos-apps | App management | npm i intentkit-macos-apps |

import { createMailProvider, type MailClient } from 'intentkit-mail';

await serve({
  registry, context,
  providers: [
    createMailProvider({
      host: 'imap.gmail.com',
      user: '[email protected]',
      password: process.env.GMAIL_APP_PASSWORD!,
      smtp: { host: 'smtp.gmail.com' },
    }),
  ],
});

// Inside functions: ctx.providers.mail as MailClient

Providers support dependency ordering (dependsOn), health checks, and graceful shutdown (destroyed in reverse init order).

Run npx intentkit list to see all adapters. Anyone can publish intentkit-{service} packages.


Agent Economy (v5.0)

Functions can declare per-call cost. Wallets track spending. Escrow holds funds for cross-service transactions.

export const analyzeData = defineFunction({
  name: 'analyze_data',
  intent: 'Run ML analysis on dataset',
  cost: { amount: 2.50, currency: 'credits', per: 'call' },
  // ...
});

// Wallet tracks spending
const wallet = new AgentWallet({ initialBalance: 100, currency: 'credits' });
wallet.spend(2.50, 'analyze_data call');

// Escrow for cross-service transactions
const escrow = new Escrow(wallet);
const entry = escrow.create({ amount: 10, payee: 'data-service', reason: 'batch analysis' });
escrow.release(entry.id); // or escrow.refund(entry.id)

// Marketplace for discovering services
const marketplace = new Marketplace();
const cheapest = marketplace.cheapest('analyze_data');

Testing

import { createTestContext } from 'intentkit/testing';

const ctx = createTestContext({ schema: './db/schema.sql', role: 'member' });
const result = await createTask.execute({ title: 'Test' }, ctx);

assert(result.id > 0);
assert(ctx.emitted[0].name === 'task.created');

ctx.withRole('viewer'); // Switch identity for permission testing
ctx.close();

In-memory SQLite. Captured events via ctx.emitted. Role switching. Zero file cleanup.

Scenario Testing

npx intentkit test scenarios/

Write multi-step test scenarios in YAML:

name: "Task lifecycle"
steps:
  - call: create_task
    input: { title: "New task" }
    expect:
      id: { type: number }
    events: [task.created]
  - call: move_task
    input: { id: 1, status: "done" }
    expect:
      success: { eq: true }

CLI

# Scaffold a new project
npx intentkit init my-api
npx intentkit init my-api --template saas-api

# Add functions
npx intentkit add create_task

# Development
npx intentkit dev src/serve.ts --watch    # Hot reload (HTTP transport)
npx intentkit dev --mock                  # Mock all adapters

# Diagnostics
npx intentkit doctor                      # Pre-flight checks
npx intentkit types                       # Generate TypeScript types
npx intentkit test scenarios/             # Run YAML test scenarios
npx intentkit docs                        # Generate documentation site
npx intentkit list                        # List available adapters

Connect to Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "my-service": {
      "command": "npx",
      "args": ["tsx", "src/serve.ts"],
      "cwd": "/path/to/my-project"
    }
  }
}

Then ask Claude: "Show me all tasks on the board" -- Claude discovers list_tasks via MCP and calls it.


Philosophy

  • Intent over interface. A function's purpose in natural language matters more than its URL path.
  • Schema over ceremony. Zod replaces DTOs, validation pipes, and serializers in one declaration.
  • Direct over abstracted. ctx.db.run(sql) over repository patterns. SQL is already a great interface.
  • Invisible over forbidden. Agents don't get 403s. They never see what they can't use.
  • Catalog over configuration. Register functions, serve. No module trees or decorator magic.

Roadmap

  • [x] defineFunction() core primitive (v0.3.0)
  • [x] Auto-generated MCP server (v0.3.0)
  • [x] SQLite context with direct db access (v0.3.0)
  • [x] Permission system with wildcards (v0.3.0)
  • [x] Capability-based discovery (v0.3.0)
  • [x] Event bus with ctx.emit() (v0.3.0)
  • [x] CLI scaffolding (v0.3.0)
  • [x] PostgreSQL context adapter (v0.4.0)
  • [x] Testing utilities (v0.4.0)
  • [x] Middleware/hooks system (v0.4.0)
  • [x] Structured logging (v0.4.0)
  • [x] HTTP transport with health checks (v0.4.0)
  • [x] Typed error handling (v0.4.0)
  • [x] Provider/adapter system (v0.5.0)
  • [x] Lifecycle manager + graceful shutdown (v0.5.0)
  • [x] Request-scoped context + requestId (v0.5.0)
  • [x] Startup validation (v0.5.0)
  • [x] Dependency-aware providers (v0.6.0)
  • [x] Composable middleware chain (v0.6.0)
  • [x] Per-request role switching (v0.6.0)
  • [x] Webhook event forwarding (v0.7.0)
  • [x] Hot reload / watch mode (v0.7.0)
  • [x] Documentation generator (v0.7.0)
  • [x] 8 service adapter packages (v1.0.0)
  • [x] Observability: observe, dashboard, OTEL, audit (v1.1.0)
  • [x] Developer tools: Studio, test runner, inspector, mock mode, doctor, types (v1.2.0)
  • [x] Agent bridges: REST, OpenAI, OpenClaw, GraphQL, WebSocket (v1.3.0)
  • [x] 6 project templates + CLI --template flag (v1.4.0)
  • [x] macOS adapters: core + 12 macOS automation packages (v1.5.0)
  • [x] defineTrigger() + watchers + condition engine + rate limiting (v2.0.0)
  • [x] Agent-to-agent: identity, discovery, trust, negotiation, mesh (v3.0.0)
  • [x] defineGoal() + persistent memory + goal tree + monitoring (v4.0.0)
  • [x] Agent economy: pricing, wallets, escrow, marketplace, contracts (v5.0.0)

79 features across 9 phases. 360 tests. 31 adapter packages. From brainstorming to v5.0 in one session.


License

MIT