pikku-mcp

star 56

Use when exposing Pikku functions as MCP tools, resources, or prompts for AI assistants. Covers mcp: true flag, pikkuMCPResourceFunc, pikkuMCPPromptFunc, and MCP wire object. TRIGGER when: code uses mcp: true or pikkuMCPResourceFunc/pikkuMCPPromptFunc, user asks about MCP, Model Context Protocol, AI tool integration, or exposing functions to Claude/ChatGPT. DO NOT TRIGGER when: user asks about AI agents (use pikku-ai-agent) or general function definitions (use pikku-concepts).

pikkujs By pikkujs schedule Updated 6/3/2026

name: pikku-mcp description: 'Use when exposing Pikku functions as MCP tools, resources, or prompts for AI assistants. Covers mcp: true flag, pikkuMCPResourceFunc, pikkuMCPPromptFunc, and MCP wire object. TRIGGER when: code uses mcp: true or pikkuMCPResourceFunc/pikkuMCPPromptFunc, user asks about MCP, Model Context Protocol, AI tool integration, or exposing functions to Claude/ChatGPT. DO NOT TRIGGER when: user asks about AI agents (use pikku-ai-agent) or general function definitions (use pikku-concepts).' installGroups: [core]

Pikku MCP Wiring

Agent Operating Procedure

Use this skill as an execution checklist, not reference material.

  1. Discover before editing. Prefer OpenCode tools such as pikku-meta when available; otherwise run the relevant pikku meta ... --json command and inspect only the focused output you need.
  2. Identify the source files that own the behavior. Do not start by reading generated output, .pikku, node_modules, vendored packages, or broad build artifacts.
  3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
  4. Validate with the narrowest relevant command first, then run pikku-verify or pikku all when functions, wirings, schemas, or generated clients may have changed.
  5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.

Expose Pikku functions as Model Context Protocol (MCP) tools, resources, and prompts for AI assistants like Claude, ChatGPT, and others.

Before You Start

pikku info functions --verbose   # See existing functions that could become MCP tools
pikku info tags --verbose        # Understand project organization

See pikku-concepts for the core mental model.

API Reference

MCP Tools (simplest approach)

Add mcp: true to any existing pikkuFunc to expose it as an MCP tool:

const myFunc = pikkuFunc({
  description: string,      // Used as MCP tool description
  input: ZodSchema,         // Becomes MCP tool input schema
  output: ZodSchema,        // Return type
  mcp: true,                // ← Expose as MCP tool
  func: async (services, data) => { ... },
})

MCP Resources (pikkuMCPResourceFunc)

import { pikkuMCPResourceFunc } from '#pikku'

const resource = pikkuMCPResourceFunc({
  uri: string,              // URI template, e.g. 'todos/{id}'
  title: string,            // Human-readable title
  description?: string,
  func: async (services, data, { mcp }) => {
    // Must return array of { uri, text } or { uri, blob, mimeType }
    return [{ uri: mcp.uri!, text: JSON.stringify(result) }]
  },
})

MCP Prompts (pikkuMCPPromptFunc)

import { pikkuMCPPromptFunc } from '#pikku'

const prompt = pikkuMCPPromptFunc({
  name: string,
  description: string,
  func: async (services, data) => {
    // Must return array of MCP messages
    return [
      {
        role: 'user',
        content: { type: 'text', text: '...' },
      },
    ]
  },
})

MCP Wire Object

Inside MCP-enabled functions, wire.mcp provides:

mcp.uri // Current resource URI (for resources)
mcp.sendResourceUpdated(uri) // Notify clients a resource changed
mcp.enableTools({ toolName: true }) // Dynamically enable/disable tools

Usage Patterns

Expose Existing Functions as MCP Tools

The simplest path — add mcp: true to any function:

export const createTodo = pikkuFunc({
  description: 'Create a new todo item',
  input: CreateTodoInput,
  output: CreateTodoOutput,
  mcp: true,
  func: async ({ db }, { text, priority }) => {
    return await db.createTodo({ text, priority })
  },
})

MCP Resources with URI Templates

export const getTodo = pikkuMCPResourceFunc({
  uri: 'todos/{id}',
  title: 'Todo Details',
  description: 'Get a todo by ID',
  func: async ({ db }, { id }, { mcp }) => {
    const todo = await db.getTodo(id)
    return [{ uri: mcp.uri!, text: JSON.stringify(todo) }]
  },
})

MCP Prompts

export const codeReview = pikkuMCPPromptFunc({
  name: 'codeReview',
  description: 'Generate a code review prompt',
  func: async ({}, { filePath, context }) => {
    return [
      {
        role: 'user',
        content: {
          type: 'text',
          text: `Review ${filePath}. Context: ${context}`,
        },
      },
    ]
  },
})

Dynamic Tool Control

export const manageTodos = pikkuFunc({
  description: 'Manage todo items',
  input: ManageTodosInput,
  output: ManageTodosOutput,
  mcp: true,
  func: async ({ db }, { action, id }, { mcp }) => {
    if (action === 'delete') {
      await db.deleteTodo(id)
      mcp.sendResourceUpdated(`todos/${id}`)
      await mcp.enableTools({ archiveTodos: true })
      return { deleted: true }
    }
  },
})

MCP Server Setup

// start.ts
import { PikkuMCPServer } from '@pikku/modelcontextprotocol'

const server = new PikkuMCPServer(config, singletonServices, createWireServices)
await server.init()
await server.start()

Complete Example

// functions/todos.functions.ts
export const listTodos = pikkuSessionlessFunc({
  description: 'List all todo items',
  input: ListTodosInput,
  output: ListTodosOutput,
  mcp: true,
  func: async ({ db }, { status }) => {
    return { todos: await db.listTodos(status) }
  },
})

export const createTodo = pikkuFunc({
  description: 'Create a new todo item',
  input: CreateTodoInput,
  output: CreateTodoOutput,
  mcp: true,
  func: async ({ db }, { text, priority }) => {
    return await db.createTodo({ text, priority })
  },
})

export const completeTodo = pikkuFunc({
  description: 'Mark a todo as complete',
  input: CompleteTodoInput,
  output: CompleteTodoOutput,
  mcp: true,
  func: async ({ db }, { todoId }) => {
    return await db.completeTodo(todoId)
  },
})

// functions/todos.mcp.ts
export const getTodoResource = pikkuMCPResourceFunc({
  uri: 'todos/{id}',
  title: 'Todo Details',
  description: 'Get details of a specific todo',
  func: async ({ db }, { id }, { mcp }) => {
    const todo = await db.getTodo(id)
    return [{ uri: mcp.uri!, text: JSON.stringify(todo) }]
  },
})

export const planDayPrompt = pikkuMCPPromptFunc({
  name: 'planDay',
  description: 'Create a daily plan based on pending todos',
  func: async ({ db }, {}) => {
    const { todos } = await db.listTodos('pending')
    return [
      {
        role: 'user',
        content: {
          type: 'text',
          text: `Plan my day. Here are my pending todos:\n${todos.map((t) => `- ${t.text} (${t.priority})`).join('\n')}`,
        },
      },
    ]
  },
})
Install via CLI
npx skills add https://github.com/pikkujs/pikku --skill pikku-mcp
Repository Details
star Stars 56
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator