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

@stackwright/mcp

v0.7.0

Published

MCP server for Stackwright — exposes content types, page management, and validation as agent tools

Readme

Stackwright MCP Server

The @stackwright/mcp package provides an MCP (Model Context Protocol) server that exposes Stackwright's content types, page management, and validation as agent tools. This enables AI agents and other MCP-compatible clients to programmatically interact with Stackwright projects.

Overview

The MCP server runs as a stdio-based service and provides tools for:

  • Content Type Introspection: Discover available content types and their schemas
  • Page Management: List, add, and validate pages in a Stackwright project
  • Site Management: Read, write, and validate site configuration; list available themes
  • Project Management: Get project information and scaffold new projects
  • Git Operations: Stage content changes and open pull requests for review
  • Visual Rendering: Screenshot pages, capture before/after diffs, verify brand consistency

Prerequisites

  • Node.js v18+
  • Stackwright monorepo cloned and built (pnpm install && pnpm build from root)

Running the Server

# From the monorepo root
pnpm stackwright-mcp

The server starts and listens on stdin/stdout for MCP protocol messages.

Available Tools

Content Type Tools

stackwright_get_content_types

List all available Stackwright content types with their fields.

Parameters: None

Returns: Text listing of all content types and sub-types with their fields

Example Usage:

const result = await server.callTool('stackwright_get_content_types', {});
// Returns: CONTENT TYPES (use as keys inside content_items[]):
//   main (main)
//     label: string
//     heading: TextBlock
//     textBlocks: TextBlock[]
//     media?: MediaItem
//     ...

Page Tools

stackwright_list_pages

List all pages in a Stackwright project.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project

Returns: Text listing of pages with slugs and headings

Example Usage:

const result = await server.callTool('stackwright_list_pages', {
  projectRoot: '/path/to/project'
});
// Returns: Pages (3):
//   about  —  About Us
//   contact  —  Contact
//   team/leadership

stackwright_add_page

Create a new page in a Stackwright project.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project
  • slug (string): Page slug (e.g., "about" or "team/leadership")
  • heading (string, optional): Optional heading for the new page

Returns: Text confirmation with created page path

Example Usage:

const result = await server.callTool('stackwright_add_page', {
  projectRoot: '/path/to/project',
  slug: 'about',
  heading: 'About Us'
});
// Returns: Created page "about" at /path/to/project/content/pages/about/content.yml

stackwright_validate_pages

Validate page YAML files against the Stackwright content schema.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project
  • slug (string, optional): Validate only this slug; omit to validate all pages

Returns: Text validation result or error messages

Example Usage:

const result = await server.callTool('stackwright_validate_pages', {
  projectRoot: '/path/to/project'
});
// Returns: ✓ Validation passed for all pages.
// Or: Validation failed:
//   [about] Missing required field: heading

Site Tools

stackwright_validate_site

Validate the stackwright.yml site configuration file.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project

Returns: Text validation result or error messages

Example Usage:

const result = await server.callTool('stackwright_validate_site', {
  projectRoot: '/path/to/project'
});
// Returns: ✓ Site config is valid (/path/to/project/stackwright.yml).

stackwright_get_site_config

Read the raw YAML content of the stackwright.yml site configuration file.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project

Returns: Text with the full YAML content of the site configuration

stackwright_write_site_config

Write or update the stackwright.yml site configuration. Validates against the site config Zod schema before writing — invalid YAML is rejected with field-level errors.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project
  • content (string): The full YAML content for the site config

Returns: Text confirmation of creation or update, or validation error details

Example Usage:

const result = await server.callTool('stackwright_write_site_config', {
  projectRoot: '/path/to/project',
  content: `title: "My Site"
navigation:
  - label: "Home"
    href: "/"
appBar:
  titleText: "My Site"
footer:
  copyright: "© 2026"
`
});
// Returns: Updated site config at /path/to/project/stackwright.yml

stackwright_list_themes

List all built-in Stackwright themes.

Parameters: None

Returns: Text listing of themes with IDs, names, and descriptions

Example Usage:

const result = await server.callTool('stackwright_list_themes', {});
// Returns: Built-in themes (3):
//   default  —  Default Theme
//   dark  —  Dark Theme: Dark mode theme
//   light  —  Light Theme: Light mode theme

Project Tools

stackwright_get_project_info

Get information about a Stackwright project.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project

Returns: Text with project info including package versions, theme, and page count

Example Usage:

const result = await server.callTool('stackwright_get_project_info', {
  projectRoot: '/path/to/project'
});
// Returns: Project root: /path/to/project
//           Site title:   My Site
//           Active theme: default
//           Pages:        5
//           Packages:
//             @stackwright/core: 0.1.0-alpha.0
//             @stackwright/nextjs: 0.1.0-alpha.0

stackwright_scaffold_project

Scaffold a new Stackwright Next.js project.

Parameters:

  • targetDir (string): Absolute path where the new project should be created
  • name (string, optional): npm package name for the new project
  • title (string, optional): Site title
  • theme (string, optional): Theme ID to use

Returns: Text confirmation with scaffolded project details

Example Usage:

const result = await server.callTool('stackwright_scaffold_project', {
  targetDir: '/path/to/new-project',
  name: 'my-stackwright-site',
  title: 'My Site',
  theme: 'default'
});
// Returns: Scaffolded project at: /path/to/new-project
//           Theme: default
//           Sample pages: about, contact, home

Git Operations Tools

stackwright_stage_changes

Stage modified or new Stackwright content files (page YAML, site config, co-located images) for commit. Only content files are staged — arbitrary files like .env or package.json are ignored for safety.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project
  • paths (string[], optional): Specific relative paths to stage (still filtered to allowed content paths)

Returns: Text listing of staged and skipped files

Allowed file patterns (relative to project root):

  • pages/**/*.{yml,yaml} and content/pages/**/*.{yml,yaml} — page content
  • pages/**/*.{png,jpg,jpeg,gif,svg,webp} and content/pages/**/*.{png,jpg,jpeg,gif,svg,webp} — co-located images
  • stackwright.{yml,yaml} — site configuration

Example Usage:

const result = await server.callTool('stackwright_stage_changes', {
  projectRoot: '/path/to/project'
});
// Returns: Staged 2 file(s):
//   + pages/about/content.yml
//   + stackwright.yml
//
// Skipped 1 non-content file(s):
//   - package.json

stackwright_open_pr

Validate all staged YAML, commit changes, push to a new branch, and open a GitHub pull request. Requires the GitHub CLI (gh) to be installed and authenticated. Aborts if validation fails — invalid YAML is never committed.

Parameters:

  • projectRoot (string): Absolute path to the root of the Stackwright project
  • title (string, optional): PR title (auto-generated from file list if omitted)
  • description (string, optional): PR body/description (auto-generated summary if omitted)
  • branchName (string, optional): Custom branch name (default: content/agent-<timestamp>)
  • baseBranch (string, optional): Target branch for the PR (default: repo default branch)
  • draft (boolean, optional): Open as a draft PR (default: false)

Returns: Text with PR URL, branch name, commit hash, and list of committed files

Prerequisites:

  • Git repository initialized with a remote named origin
  • GitHub CLI installed and authenticated (gh auth login)
  • Content changes staged via stackwright_stage_changes

Example Usage:

const result = await server.callTool('stackwright_open_pr', {
  projectRoot: '/path/to/project',
  title: 'Add services page',
  baseBranch: 'dev'
});
// Returns: Pull request opened: https://github.com/org/repo/pull/42
//           Branch: content/agent-20260306-143022
//           Commit: a1b2c3d4
//           Files committed (1):
//             pages/services/content.yml

Visual Rendering Tools

stackwright_check_dev_server

Check if a Stackwright dev server is running and reachable. Call this before using render tools.

Parameters:

  • baseUrl (string, optional): Base URL to check (default: http://localhost:3000)

Returns: Text confirming server is reachable, or error with instructions to start the dev server

Example Usage:

const result = await server.callTool('stackwright_check_dev_server', {});
// Returns: ✓ Dev server is running at http://localhost:3000. You can now use stackwright_render_page to see your pages.

stackwright_render_page

Render a Stackwright page and return a screenshot image. Use this to visually verify how a page looks after writing or editing content. Requires a running dev server.

Parameters:

  • baseUrl (string, optional): Base URL of the running dev server (default: http://localhost:3000)
  • slug (string): Page slug to render (e.g., "/" for home, "/about", "/pricing")
  • viewport (object, optional): { width: number, height: number } — viewport size (default: 1280x720). Use 375x667 for mobile.
  • fullPage (boolean, optional): Capture full scrollable page or just the viewport (default: true)
  • format (string, optional): Image format — "png" or "jpeg" (default: "png")

Returns: Text with render metadata plus a PNG/JPEG screenshot image

Example Usage:

const result = await server.callTool('stackwright_render_page', {
  slug: '/about',
  viewport: { width: 375, height: 667 }
});
// Returns: Rendered "/about" (375x667, 1234ms):
// [image: screenshot of the rendered page]

stackwright_render_diff

Capture a "before" screenshot of a page for visual comparison. After capturing, make your YAML changes and call stackwright_render_page to see the "after" state.

Parameters:

  • baseUrl (string, optional): Base URL of the running dev server (default: http://localhost:3000)
  • slug (string): Page slug to snapshot
  • viewport (object, optional): { width: number, height: number } — viewport size
  • fullPage (boolean, optional): Capture full scrollable page (default: true)

Returns: Text with snapshot metadata plus a "before" PNG screenshot

Workflow:

  1. Call stackwright_render_diff to capture the current state
  2. Write your YAML changes (stackwright_write_page or stackwright_compose_site)
  3. Wait for the dev server to hot-reload
  4. Call stackwright_render_page to see the "after" state
  5. Compare the two images to evaluate your changes

Example Usage:

const result = await server.callTool('stackwright_render_diff', {
  slug: '/pricing'
});
// Returns: 📸 "Before" snapshot captured for "/pricing" (1280x720, 987ms).
// [image: screenshot of the current page state]

Integration with MCP Clients

The Stackwright MCP server follows the Model Context Protocol (MCP) specification. Any MCP-compatible client can connect to and use these tools.

Example: Full editorial loop (content authoring → PR)

import { McpClient } from '@modelcontextprotocol/sdk/client/mcp.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';

const client = new McpClient();
await client.connect(new StdioClientTransport());

try {
  const projectRoot = '/path/to/project';

  // 1. Understand available content types
  const contentTypes = await client.callTool('stackwright_get_content_types', {});

  // 2. Create a new page
  await client.callTool('stackwright_add_page', {
    projectRoot,
    slug: 'services',
    heading: 'Our Services',
  });

  // 3. Validate
  const validation = await client.callTool('stackwright_validate_pages', {
    projectRoot,
    slug: 'services',
  });

  if (validation.isError) {
    console.error('Validation failed:', validation.content[0].text);
    return;
  }

  // 4. Stage content changes (only content files are staged)
  const staged = await client.callTool('stackwright_stage_changes', { projectRoot });
  console.log(staged.content[0].text);

  // 5. Open a PR for human review
  const pr = await client.callTool('stackwright_open_pr', {
    projectRoot,
    title: 'Add services page',
    baseBranch: 'dev',
  });
  console.log(pr.content[0].text); // PR URL
} finally {
  await client.disconnect();
}

Best Practices

  1. Always validate after creating or modifying content — call stackwright_validate_pages after stackwright_add_page.
  2. Use stackwright_get_content_types to ground your YAML — the tool returns the live Zod-derived schema, so field names and required/optional status are always current.
  3. Check isError on every response — tools signal errors via the isError flag rather than throwing, so a successful HTTP-level call can still represent a domain error.
  4. Use absolute paths — all projectRoot and targetDir parameters must be absolute paths.
  5. Disconnect in a finally block — always call client.disconnect() to avoid leaving the server process orphaned.
  6. Render after editing — call stackwright_render_page after making content changes to visually verify the result. This catches layout, spacing, and brand consistency issues that schema validation alone cannot detect.
  7. Check the dev server first — always call stackwright_check_dev_server before any render tool. If the server isn't running, render tools will fail with a clear error.

Development

Building

cd packages/mcp
pnpm build

Testing

cd packages/mcp
pnpm test

Running in Development Mode

cd packages/mcp
pnpm dev

Architecture

The MCP server is built on top of the @modelcontextprotocol/sdk and exposes functionality from the @stackwright/cli package as MCP tools. Each tool corresponds to a CLI command but is adapted for programmatic use.

Tool Registration Pattern

server.tool(
  'tool_name',
  'Tool description',
  {
    param1: z.string().describe('Description'),
    param2: z.number().optional().describe('Optional description'),
  },
  async ({ param1, param2 }) => {
    return { content: [{ type: 'text', text: 'Result' }] };
  }
);

Error Handling

Tools return structured responses with:

  • content: Array of content items (text, images, etc.)
  • isError: Boolean flag indicating if the response represents an error
{
  "content": [{ "type": "text", "text": "Validation failed:\n  [about] Missing required field: heading" }],
  "isError": true
}

Troubleshooting

Server not responding — ensure the server is running with pnpm stackwright-mcp and that stdin/stdout are properly connected to the client.

Tool not found — verify the tool name is correct (all tool names are prefixed with stackwright_).

Validation failures — check the structured error text for specific field issues; use stackwright_get_content_types to confirm required fields.

Permission errors on file operations — use absolute paths and ensure the server process has write access to the target directory.

Version Compatibility

  • @modelcontextprotocol/sdk: ^1.27.0
  • @stackwright/cli: Same workspace version
  • Node.js: ^18.0.0 or later

License

MIT License. See the LICENSE file for details.

Support

  • GitHub Issues: https://github.com/Per-Aspera-LLC/stackwright/issues