@openpets/uk-postcodes
v1.0.0
Published
Free, open-source UK postcode lookup and geocoding via Postcodes.io. Resolve administrative and location data for postcodes, perform reverse geocoding, nearest postcode search, postcode validation and autocomplete. No authentication required.
Maintainers
Readme
Pet Plugin Template
A comprehensive template demonstrating OpenPets best practices. Copy this folder and customize it to build your own pet.
Best Practices Demonstrated
This template includes all required patterns:
- Test Connection Tool - Every pet MUST have
{pet-name}-test-connection - Graceful Degradation - Returns limited toolset when not configured
- Proper Tool Naming - All tools follow
{pet-name}-{action}pattern - Structured Responses - All tools return JSON with success/error status
- Environment Handling - Uses
loadEnv()for configuration - Logging - Uses
createLogger()for debugging
Quick Start
1. Copy This Template
# From the pets directory
cp -r _TEMPLATE_ my-pet
cd my-pet2. 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_here5. Test Your Pet
bun install
opencode run "test my-pet connection" --print-logsTool 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:
- Works even when the pet is not configured
- Returns structured status information
- 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 arraysz.record()- No record typesz.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_URLDocument 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-connectiontool - [ ] 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 validatepasses
Publishing
# Validate first
pets validate
# Preview what will be published
pets publish --preview
# Publish to npm
pets publishExamples
For real-world examples, check out:
pets/jira/- Full-featured with 20+ toolspets/github/- GitHub API integrationpets/stripe/- Payment processingpets/wise/- Financial services
Need Help?
- AGENTS.md - Comprehensive development guide
- docs/best-practices.md - Best practices
- docs/testing.md - Testing guide
