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

@cursor-ai/january

v0.2.1

Published

Experimental project

Readme

@anysphere/cursor-sdk

Public SDK for Cursor Agent APIs.

Agent SDK

The Agent SDK provides stable, backwards-compatible types for working with Cursor Agent messages, tool calls, and results.

Installation

import {
  UserMessage,
  ToolCall,
  Message,
} from "@anysphere/cursor-sdk/agent-sdk";

Message Types

  • UserMessage: Messages from users to the agent
  • AssistantMessage: Messages from the AI assistant
  • ToolCall: Tool invocations made by the agent
  • ToolResult: Results from tool executions

All messages include a session_id field to group related messages in a conversation.

Example

import { Message, isToolCall } from "@anysphere/cursor-sdk/agent-sdk";

const message: Message = {
  type: "tool_call",
  session_id: "abc123",
  name: "read_file",
  input: { path: "/path/to/file.ts" },
};

if (isToolCall(message)) {
  console.log(`Calling tool: ${message.name}`);
}

Tool Names

The SDK supports two categories of tools:

First-Party Tools

The SDK maps internal tool names to public-friendly names:

  • readToolCallread_file
  • shellToolCallrun_terminal_cmd
  • grepToolCallgrep
  • etc.

Use normalizeToolName() to convert proto tool names to public API names.

MCP Tools

MCP (Model Context Protocol) tools follow the naming convention mcp__provider__tool:

  • mcp__filesystem__read_file - File system provider's read_file tool
  • mcp__database__query_table - Database provider's query_table tool
  • mcp__github__create_issue - GitHub provider's create_issue tool

Working with MCP Tools

import {
  isMcpTool,
  parseMcpToolName,
  createMcpToolName,
  McpToolInput,
  McpToolResult,
} from "@anysphere/cursor-sdk/agent-sdk";

// Check if a tool is an MCP tool
const toolName = "mcp__github__create_issue";
if (isMcpTool(toolName)) {
  console.log("This is an MCP tool");
}

// Parse MCP tool name
const parsed = parseMcpToolName(toolName);
if (parsed) {
  console.log(`Provider: ${parsed.provider}, Tool: ${parsed.tool}`);
  // Output: Provider: github, Tool: create_issue
}

// Create MCP tool name
const mcpToolName = createMcpToolName("database", "query_table");
console.log(mcpToolName); // mcp__database__query_table

// MCP tool call example
const mcpToolCall: Message = {
  type: "tool_call",
  session_id: "abc123",
  name: "mcp__github__create_issue",
  input: {
    title: "Bug report",
    body: "Found an issue...",
    labels: ["bug", "high-priority"],
  },
};

MCP Tool Input/Output

MCP tools use flexible input/output schemas:

  • Input: Any JSON-serializable object (McpToolInput)
  • Output: MCP-compliant result format with content array (McpToolResult)
import { McpToolResult } from "@anysphere/cursor-sdk/agent-sdk";

const mcpResult: McpToolResult = {
  content: [
    {
      type: "text",
      text: "Issue #123 created successfully",
    },
    {
      type: "resource",
      resource: {
        uri: "https://github.com/owner/repo/issues/123",
        text: "View the created issue",
        mimeType: "text/html",
      },
    },
  ],
  isError: false,
};

Streaming Delta Types

For streaming interactions, the SDK exposes delta/update types mirroring internal interaction updates:

import type {
  InteractionUpdate,
  TextDeltaUpdate,
  ThinkingDeltaUpdate,
  ToolCallStartedUpdate,
  ToolCallCompletedUpdate,
  SummaryStartedUpdate,
  SummaryCompletedUpdate,
  ShellOutputDeltaUpdate,
  InteractionListener,
} from "@anysphere/cursor-sdk/agent-sdk";

function handleUpdate(update: InteractionUpdate) {
  switch (update.type) {
    case "text-delta": {
      // handle streaming assistant text
      break;
    }
    case "tool-call-started": {
      // update UI with pending tool call
      break;
    }
    case "tool-call-completed": {
      // display tool result
      break;
    }
    case "shell-output-delta": {
      // stream shell output events
      break;
    }
  }
}

Simple Agent SDK (MVP)

import { CursorAgent, type WorkingLocation } from "@anysphere/cursor-sdk/agent";

const workingLocation: WorkingLocation =
  process.env.REPO_URL
    ? { type: "github", repository: process.env.REPO_URL!, ref: process.env.REPO_REF ?? "main" }
    : { type: "local", localDirectory: process.cwd() };

const agent = new CursorAgent({ apiKey: process.env.CURSOR_API_KEY!, model: "gpt-4o", workingLocation });

// Option 1: Stream the deltas in real-time
const { stream, conversation } = agent.submit({
  message: "Refactor the utils module",
});

for await (const delta of stream) {
  // Handle InteractionUpdate deltas
}

const turns = await conversation; // Resolves after stream is consumed

// Option 2: Use callbacks for step-by-step updates
const result = agent.submit({
  message: "Refactor the utils module",
  onStep: ({ step }) => {
    // Called when each step completes (assistant text, tool calls, thinking)
    console.log("Step completed:", step);
  },
  onDelta: ({ update }) => {
    // Called on every delta (text-delta, tool-call-completed, etc.)
    console.log("Delta:", update.type);
  },
});

// Option 3: Just wait for the conversation to complete
const turns = await agent.submit({ message: "..." }).conversation;

// Option 4: Inspect conversation at any time (returns shallow copy)
const currentConversation = agent.conversation();

// Notes
// - When using { type: "github" }, the SDK creates a cloud agent and immediately
//   streams updates via the public SSE endpoint (`/v0/agents/:id/conversation/stream`).
// - Abort for cloud agents is not supported and will throw a NotSupported error.
// - Follow-up messages require a separate endpoint; see the Cloud Agent API docs:
//   https://cursor.com/docs/background-agent/api/endpoints