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

@executor-js/sdk

v0.0.1

Published

A TypeScript SDK for building executors that wire together tool sources, secrets, and policies across MCP, OpenAPI, GraphQL, and custom plugins.

Downloads

1,395

Readme

@executor/sdk

A TypeScript SDK for building executors that wire together tool sources, secrets, and policies across MCP, OpenAPI, GraphQL, and custom plugins.

Everything is async/await. Plug in any combination of plugins, register your own tools, and invoke them through a unified catalog.

Install

bun add @executor/sdk
# or
npm install @executor/sdk

Quick start

import {
  createExecutor,
  definePlugin,
  ToolRegistration,
  ToolId,
  ToolInvocationResult,
} from "@executor/sdk";

// Define a custom plugin with async/await.
const weatherPlugin = definePlugin({
  key: "weather",
  init: async (ctx) => {
    await ctx.tools.registerInvoker("weather", {
      invoke: async (_toolId, args) => {
        const { city } = args as { city: string };
        return new ToolInvocationResult({
          data: { city, temperature: 72, condition: "sunny" },
          error: null,
        });
      },
    });

    await ctx.tools.register([
      new ToolRegistration({
        id: ToolId.make("weather.getForecast"),
        pluginKey: "weather",
        sourceId: "weather",
        name: "getForecast",
        description: "Get weather forecast for a city",
        inputSchema: {
          type: "object",
          properties: { city: { type: "string" } },
          required: ["city"],
        },
      }),
    ]);

    return {
      extension: {
        forecast: async (city: string) => {
          const result = await ctx.tools.invoke(
            "weather.getForecast",
            { city },
            { onElicitation: "accept-all" },
          );
          return result.data as { city: string; temperature: number; condition: string };
        },
      },
    };
  },
});

const executor = await createExecutor({
  scope: { name: "my-app" },
  plugins: [weatherPlugin] as const,
});

// The plugin's extension is available under its key.
const forecast = await executor.weather.forecast("San Francisco");

// Every plugin contributes to a unified tool catalog.
const tools = await executor.tools.list();

// Invoke any tool with the same call shape.
const result = await executor.tools.invoke(
  "weather.getForecast",
  { city: "Tokyo" },
  { onElicitation: "accept-all" },
);

await executor.close();

Using plugins

Install whichever plugins you need and pass their factory call into plugins:

import { createExecutor } from "@executor/sdk";
import { mcpPlugin } from "@executor/plugin-mcp";
import { openApiPlugin } from "@executor/plugin-openapi";
import { graphqlPlugin } from "@executor/plugin-graphql";

const executor = await createExecutor({
  scope: { name: "my-app" },
  plugins: [mcpPlugin(), openApiPlugin(), graphqlPlugin()] as const,
});

await executor.mcp.addSource({
  transport: "remote",
  name: "Context7",
  endpoint: "https://mcp.context7.com/mcp",
});
await executor.openapi.addSpec({
  spec: "https://petstore3.swagger.io/api/v3/openapi.json",
  namespace: "petstore",
});
await executor.graphql.addSource({ endpoint: "https://graphql.anilist.co", namespace: "anilist" });

const tools = await executor.tools.list();

Available plugins:

Secrets

Secrets are scoped per executor and shared across every plugin that resolves them:

await executor.secrets.set({
  id: "github-token",
  name: "GitHub Token",
  value: "ghp_...",
  purpose: "authentication",
});

const value = await executor.secrets.resolve("github-token");

Plugins accept { secretId, prefix } wherever a header value is expected, so you never write tokens into source configs.

Using with Effect

The SDK is built on Effect under the hood. If you want the raw Effect-based primitives instead of the promise wrapper, import from the /core subpath:

import { createExecutor } from "@executor/sdk";

/core exposes createExecutor returning an Effect, the ToolRegistry / SourceRegistry / SecretStore / PolicyEngine Context tags, the in-memory store factories, and every branded ID + error class. Every @executor/plugin-* ships a matching /core subpath.

Status

Pre-1.0. APIs may still change between beta releases. See the executor monorepo for the current development branch and roadmap.

License

MIT