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

@openpets/luma

v1.0.3

Published

Manage events, guests, calendars, and ticketing through the Luma API. Create events, manage registrations, send invites, and more.

Readme

Pet Plugin Template

A comprehensive template demonstrating OpenPets best practices. Copy this folder and customize it to build your own pet.

Luma API Key Setup

  • Developer settings URL format: https://luma.com/calendar/manage/{calendar_id}/settings/developer
  • Replace {calendar_id} with your real calendar id from your Luma calendar URL
  • Store the id as LUMA_CALENDAR_ID (optional helper)
  • Store the generated API key as LUMA_API_KEY (required)

Best Practices Demonstrated

This template includes all required patterns:

  1. Test Connection Tool - Every pet MUST have {pet-name}-test-connection
  2. Graceful Degradation - Returns limited toolset when not configured
  3. Proper Tool Naming - All tools follow {pet-name}-{action} pattern
  4. Structured Responses - All tools return JSON with success/error status
  5. Environment Handling - Uses loadEnv() for configuration
  6. Logging - Uses createLogger() for debugging

Quick Start

1. Copy This Template

# From the pets directory
cp -r _TEMPLATE_ my-pet
cd my-pet

2. Update package.json

Change these fields:

{
  "name": "@openpets/my-pet",
  "title": "My Pet",
  "description": "What my pet does",
  "envVariables": {
    "required": [
      {
        "name": "MY_PET_API_KEY",
        "description": "API key from My Service"
      }
    ]
  },
  "queries": [
    "test my-pet connection",
    "list items from my-pet"
  ]
}

3. Update index.ts

export const MyPetPlugin = async () => {
  const logger = createLogger("my-pet")
  const env = loadEnv("my-pet")  // Loads MY_PET_* variables
  
  const API_KEY = env.MY_PET_API_KEY
  const isConfigured = !!API_KEY
  
  if (!isConfigured) {
    // Return limited toolset when not configured
    return createPlugin([
      {
        name: "my-pet-test-connection",
        description: "Test my-pet connection status",
        schema: z.object({}),
        async execute() {
          return JSON.stringify({
            success: false,
            status: "not_configured",
            message: "Please set MY_PET_API_KEY"
          }, null, 2)
        }
      }
    ])
  }
  
  // Return full toolset when configured
  const tools: ToolDefinition[] = [
    {
      name: "my-pet-test-connection",
      // ... full implementation
    },
    {
      name: "my-pet-list-items",
      // ... your tools
    }
  ]
  
  return createPlugin(tools)
}

4. Update .env.example

# My Pet Configuration
MY_PET_API_KEY=your_api_key_here

5. Test Your Pet

bun install
opencode run "test my-pet connection" --print-logs

Tool Naming Convention

All tools MUST follow the pattern: {pet-name}-{action}

| Good | Bad | |------|-----| | jira-list-issues | list-issues | | github-create-pr | create-pr | | stripe-get-customer | getCustomer | | my-pet-test-connection | test-connection |

Required: Test Connection Tool

Every pet MUST have a test-connection tool that:

  1. Works even when the pet is not configured
  2. Returns structured status information
  3. Provides helpful error messages
{
  name: "my-pet-test-connection",
  description: "Test connection and configuration status",
  schema: z.object({}),
  async execute() {
    return JSON.stringify({
      success: true,  // or false
      status: "connected",  // or "not_configured", "error"
      message: "Connected successfully",
      details: {
        // Add relevant details
      }
    }, null, 2)
  }
}

Graceful Degradation

When your pet is not configured, return a limited toolset:

if (!isConfigured) {
  logger.warn("Pet not configured - returning limited toolset")
  return createPlugin([
    // Only include test-connection tool
    testConnectionTool
  ])
}

// Full toolset when configured
return createPlugin(allTools)

Response Format

Always return JSON strings with consistent structure:

// Success response
return JSON.stringify({
  success: true,
  data: result,
  message: "Operation completed"
}, null, 2)

// Error response
return JSON.stringify({
  success: false,
  error: error.message,
  code: "INVALID_INPUT"  // optional error code
}, null, 2)

// List response
return JSON.stringify({
  success: true,
  total: items.length,
  items: items
}, null, 2)

Schema Types (Zod)

Use these supported Zod types:

schema: z.object({
  // Primitives
  name: z.string().describe("User name"),
  age: z.number().describe("User age"),
  active: z.boolean().describe("Is active"),
  
  // Optional with default
  limit: z.number().optional().default(50).describe("Max results"),
  
  // Enum
  status: z.enum(["active", "archived"]).describe("Status filter"),
  
  // Arrays (primitives only)
  tags: z.array(z.string()).describe("Tags list"),
  ids: z.array(z.number()).describe("ID list")
})

NOT supported (will cause errors):

  • z.array(z.object({...})) - No nested objects in arrays
  • z.record() - No record types
  • z.union() with objects - No complex unions

For complex data, use JSON strings:

schema: z.object({
  filtersJson: z.string().describe("JSON string of filter options")
}),
execute(args) {
  const filters = JSON.parse(args.filtersJson)
}

Environment Variables

Use loadEnv() from openpets-sdk:

const env = loadEnv("my-pet")

// This loads variables with the prefix:
// MY_PET_API_KEY -> env.MY_PET_API_KEY
// MY_PET_BASE_URL -> env.MY_PET_BASE_URL

Document in package.json:

{
  "envVariables": {
    "required": [
      {
        "name": "MY_PET_API_KEY",
        "description": "API key from My Service",
        "provider": "My Service",
        "priority": 1
      }
    ],
    "optional": [
      {
        "name": "MY_PET_DEBUG",
        "description": "Enable debug logging",
        "provider": "Configuration",
        "priority": 2
      }
    ]
  }
}

Logging

Use the logger for debugging:

const logger = createLogger("my-pet")

logger.debug("Debug info", { context: data })
logger.info("Operation started")
logger.warn("Warning message")
logger.error("Error occurred", { error: err.message })

Validation Checklist

Before publishing, verify:

  • [ ] Package name is @openpets/my-pet
  • [ ] Has my-pet-test-connection tool
  • [ ] Test-connection works when NOT configured
  • [ ] All tool names follow my-pet-{action} pattern
  • [ ] All tools return JSON strings
  • [ ] Environment variables documented in package.json
  • [ ] .env.example has all variables
  • [ ] queries array has example prompts
  • [ ] pets validate passes

Publishing

# Validate first
pets validate

# Preview what will be published
pets publish --preview

# Publish to npm
pets publish

Examples

For real-world examples, check out:

  • pets/jira/ - Full-featured with 20+ tools
  • pets/github/ - GitHub API integration
  • pets/stripe/ - Payment processing
  • pets/wise/ - Financial services

Need Help?