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

sunpeak

v0.16.14

Published

Local-first MCP Apps framework. Quickstart, build, test, and ship your Claude or ChatGPT App!

Downloads

4,411

Readme

sunpeak

npm version npm downloads stars CI License TypeScript React

Local-first MCP Apps framework.

Quickstart, build, test, and ship your Claude or ChatGPT App!

Demo (Hosted) ~ Demo (Video) ~ Discord ~ Documentation ~ GitHub

Quickstart

Requirements: Node (20+), pnpm (10+)

pnpm add -g sunpeak
sunpeak new

Overview

sunpeak is an npm package that helps you build MCP Apps (interactive UI resources) while keeping your MCP server client-agnostic. Built on the MCP Apps SDK (@modelcontextprotocol/ext-apps). sunpeak consists of:

The sunpeak library

  1. Runtime APIs: Strongly typed React hooks for interacting with the host runtime (useApp, useToolData, useAppState, useHostContext, useUpdateModelContext, useAppTools), architected to support generic and platform-specific features (ChatGPT, Claude, etc.). Platform-specific hooks like useUploadFile, useRequestModal, and useRequestCheckout are available via sunpeak/platform/chatgpt, with isChatGPT() / isClaude() platform detection via sunpeak/platform.
  2. Multi-host simulator: React component replicating host runtimes (ChatGPT, Claude) to test Apps locally and automatically via UI, props, or URL parameters.
  3. MCP server: Serve Resources with mock data to hosts like ChatGPT and Claude with HMR (no more cache issues or 5-click manual refreshes).

The sunpeak framework

Next.js for MCP Apps. Using an example App my-app with a Review UI (MCP resource), sunpeak projects look like:

my-app/
├── src/
│   ├── resources/
│   │   └── review/
│   │       └── review.tsx   # Review UI component + resource metadata.
│   ├── tools/
│   │   ├── review-diff.ts   # Tool with handler, schema, and resource reference.
│   │   └── review-post.ts   # Multiple tools can share one resource.
│   └── server.ts            # Optional: auth, server config.
├── tests/simulations/
│   ├── review-diff.json     # Mock state for testing.
│   └── review-post.json     # Mock state for testing.
└── package.json
  1. Project scaffold: Complete development setup with the sunpeak library.
  2. UI components: Production-ready components following MCP App design guidelines.
  3. Convention over configuration:
    1. Create a UI by creating a .tsx file in src/resources/{name}/ that exports a ResourceConfig and a React component (example below).
    2. Create a tool by creating a .ts file in src/tools/ that exports tool (metadata with resource reference), schema (Zod), and a default handler (example below).
    3. Create test state (Simulations) by creating a .json file in tests/simulations/ (example below).

The sunpeak CLI

Commands for managing MCP Apps:

  • sunpeak new [name] [resources] - Create a new project
  • sunpeak dev - Start dev server with MCP endpoint and live simulator
  • sunpeak build - Build resources and compile tools for production
  • sunpeak start - Start the production MCP server (real handlers, auth, Zod validation)
  • sunpeak upgrade - Upgrade sunpeak to latest version

Example App

Example Resource, Simulation, and testing file (using the Simulator) for an MCP resource called "Review".

Resource Component

Each resource .tsx file exports both the React component and the MCP resource metadata:

// src/resources/review/review.tsx

import { useToolData } from 'sunpeak';
import type { ResourceConfig } from 'sunpeak';

export const resource: ResourceConfig = {
  description: 'Visualize and review a code change',
  _meta: { ui: { csp: { resourceDomains: ['https://cdn.example.com'] } } },
};

export function ReviewResource() {
  const { output: data } = useToolData<unknown, { title: string }>();

  return <h1>Review: {data?.title}</h1>;
}

Tool File

Each tool .ts file exports metadata (with a direct resource reference), a Zod schema, and a handler:

// src/tools/review-diff.ts

import { z } from 'zod';
import type { AppToolConfig, ToolHandlerExtra } from 'sunpeak/mcp';

export const tool: AppToolConfig = {
  resource: 'review',
  title: 'Diff Review',
  description: 'Show a review dialog for a proposed code diff',
  annotations: { readOnlyHint: false },
  _meta: { ui: { visibility: ['model', 'app'] } },
};

export const schema = {
  changesetId: z.string().describe('Unique identifier for the changeset'),
  title: z.string().describe('Title describing the changes'),
};

type Args = z.infer<z.ZodObject<typeof schema>>;

export default async function (args: Args, extra: ToolHandlerExtra) {
  return { structuredContent: { title: args.title, sections: [] } };
}

Simulation

Simulation files provide fixture data for testing. Each references a tool by filename and contains the mock input/output:

// tests/simulations/review-diff.json

{
  "tool": "review-diff",                      // References src/tools/review-diff.ts
  "userMessage": "Refactor the auth module to use JWT tokens.",
  "toolInput": {
    "changesetId": "cs_789",
    "title": "Refactor Authentication Module"
  },
  "toolResult": {
    "structuredContent": {
      "title": "Refactor Authentication Module",
      "sections": [...]
    }
  }
}

Simulator

├── tests/e2e/
│   └── review.spec.ts # This! (not pictured above for simplicity)
└── package.json

The Simulator allows you to set host state (like host platform, light/dark mode) via URL params, which can be rendered alongside your Simulations and tested via pre-configured Playwright end-to-end tests (.spec.ts).

Using the Simulator and Simulations, you can test all possible App states locally and automatically across hosts (ChatGPT, Claude)!

// tests/e2e/review.spec.ts

import { test, expect } from '@playwright/test';
import { createSimulatorUrl } from 'sunpeak/simulator';

const hosts = ['chatgpt', 'claude'] as const;

for (const host of hosts) {
  test.describe(`Review Resource [${host}]`, () => {
    test.describe('Light Mode', () => {
      test('should render review title with correct styles', async ({ page }) => {
        const params = { simulation: 'review-diff', theme: 'light', host }; // Set sim & host state.
        await page.goto(createSimulatorUrl(params));

        // Resource content renders inside an iframe
        const iframe = page.frameLocator('iframe');
        const title = iframe.locator('h1:has-text("Refactor Authentication Module")');
        await expect(title).toBeVisible();

        const color = await title.evaluate((el) => window.getComputedStyle(el).color);

        // Light mode should render dark text.
        expect(color).toBe('rgb(13, 13, 13)');
      });
    });
  });
}

Coding Agent Skill

Install the create-sunpeak-app skill to give your coding agent (Claude Code, Cursor, etc.) built-in knowledge of sunpeak patterns, hooks, simulation files, and testing conventions:

npx skills add Sunpeak-AI/sunpeak@create-sunpeak-app

Resources