You're viewing a demo portfolio

Join the waitlist
PRSM
This tool is no longer present in the server's latest manifest. Showing the last observed version (server version 0.1.0).

deploy_function

Inactive

Tool of io.github.butterbase-ai/mcp

declared in 0.1.0

Deploy or update a serverless function with custom business logic. Example: Input: { app_id: "app_abc123", name: "send-welcome-email", code: "export async function handler(req, ctx) { ... }", trigger: { type: "http", config: { method: "POST", path: "/welcome", auth: "required" } } } Output: { function_id: "fn_xyz789", name: "send-welcome-email", url: "https://api.butterbase.ai/v1/app_abc123/fn/send-welcome-email", status: "deployed" } Function signature: export async function handler(request: Request, context: { db: PostgresClient, // Query your app database env: Record<string, string>, // Access envVars user: { id: string } | null, // Current user (if auth: required) waitUntil: (promise: Promise) => void, // Keep alive for background work after response idempotency: { // Webhook / event dedup primitive claim: (key: string, opts?: { scope?: string; ttlSeconds?: number }) => Promise<boolean> } }): Promise<Response> Console output: console.log(), console.info(), console.warn(), console.error(), and console.debug() calls are captured and stored with invocation logs. View them via manage_function (action: "get_logs"). IMPORTANT: Handlers MUST return a Response object (Web API standard). Do NOT return plain objects like { status: 200, body: "..." }. Idempotent webhook handlers with ctx.idempotency.claim(): Third-party webhook providers (Stripe, Telegram, GitHub, Slack, Twilio, Discord) retry delivery on non-2xx responses with the same event id. Use ctx.idempotency.claim() to atomically dedupe — it returns true if you're the first to see this key, false if another invocation already claimed it. export async function handler(req, ctx) { const event = await req.json(); if (!(await ctx.idempotency.claim(event.id))) { // Already processed — ack the retry without re-doing work. return new Response('duplicate', { status: 200 }); } await processEvent(event); return new Response('ok', { status: 200 }); } Options: - scope: 'stripe' | 'telegram' | ... (default: 'default'). Namespace claims so keys from different providers can never collide. - ttlSeconds: mark the claim with an expiry. Cleanup is your responsibility: DELETE FROM _idempotency_keys WHERE expires_at < now(); Background work with ctx.waitUntil(): Use ctx.waitUntil(promise) to keep the function alive after the response is sent. This is useful for fire-and-forget tasks like sending emails or logging. Background work has a 30-second timeout. ctx.db is available inside waitUntil promises. export async function handler(req, ctx) { ctx.waitUntil(fetch("https://api.email.com/send", { method: "POST", body: "..." })); return new Response(JSON.stringify({ accepted: true }), { headers: { "Content-Type": "application/json" } }); } Example: export async function handler(req, ctx) { const data = { hello: "world" }; return new Response(JSON.stringify(data), { status: 200, headers: { "Content-Type": "application/json" } }); } Row-Level Security in Functions: Functions respect RLS policies based on how they're invoked: - Invoked with end-user JWT → butterbase_user role (RLS enforced) * ctx.db queries see only the user's data * ctx.user.id contains the authenticated user ID * Use case: User-facing operations - Invoked with platform API key → butterbase_service role (RLS bypassed) * ctx.db queries see all data * ctx.user is null * Use case: Admin operations, background jobs - Invoked by cron trigger → butterbase_service role (RLS bypassed) * ctx.db queries see all data * ctx.user is null * Use case: Scheduled tasks, cleanup jobs Trigger types: - http: Invoke via HTTP request (GET, POST, etc) - cron: Schedule periodic execution (e.g., "0 9 * * *" = daily at 9am) - websocket: Trigger on WebSocket event from client via realtime connection - s3_upload: Trigger on file upload [not yet implemented] - webhook: Receive webhooks from external services [not yet implemented] Common errors: - VALIDATION_INVALID_SCHEMA: Check code exports a handler function - RESOURCE_NOT_FOUND: App doesn't exist - Syntax error: Code must be valid TypeScript/JavaScript Idempotency: Safe to call multiple times (updates existing function with same name). Next steps: Use invoke_function to test, then manage_function (action: "get_logs") to debug.

Parameters schema

{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "app_id",
    "name",
    "code"
  ],
  "properties": {
    "code": {
      "type": "string",
      "description": "TypeScript/JavaScript code that exports a handler function"
    },
    "name": {
      "type": "string",
      "description": "Function name (alphanumeric, hyphens, underscores)"
    },
    "app_id": {
      "type": "string",
      "description": "The app ID to deploy the function to"
    },
    "envVars": {
      "type": "object",
      "description": "Environment variables (will be encrypted)",
      "additionalProperties": {
        "type": "string"
      }
    },
    "trigger": {
      "type": "object",
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "enum": [
            "http",
            "cron",
            "s3_upload",
            "webhook",
            "websocket"
          ],
          "type": "string",
          "description": "Trigger type"
        },
        "config": {
          "description": "Trigger-specific config (see triggers param for shape)."
        }
      },
      "description": "Single-trigger shorthand. Prefer `triggers` for new code; this is kept for back-compat.",
      "additionalProperties": false
    },
    "triggers": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "enum": [
              "http",
              "cron",
              "s3_upload",
              "webhook",
              "websocket"
            ],
            "type": "string",
            "description": "Trigger type: http, cron, s3_upload, webhook, or websocket"
          },
          "config": {
            "description": "Trigger-specific configuration:\n- http: { method?: string, path?: string, auth?: 'required'|'optional'|'none' }\n  * auth defaults to 'required' for new HTTP functions — anonymous callers get 401 at the edge.\n  * Set auth: 'none' ONLY for intentionally public endpoints. Inside such a function, ctx.db runs\n    as butterbase_service (RLS bypassed), so guard every DB access manually or hand-check ctx.user.\n- cron: { schedule: string (cron expression like \"0 9 * * *\"), timezone?: string (default: UTC) }\n- s3_upload: { bucket: string, prefix?: string, contentTypes?: string[] }\n- webhook: { secret_required?: boolean, allowed_sources?: string }\n- websocket: {} Trigger on incoming WebSocket frames"
          },
          "enabled": {
            "type": "boolean",
            "description": "Default true."
          }
        },
        "additionalProperties": false
      },
      "minItems": 1,
      "description": "Canonical multi-trigger array. At most one trigger per type."
    },
    "timeoutMs": {
      "type": "number",
      "description": "Execution timeout in milliseconds (default: 30000)"
    },
    "agent_tool": {
      "type": "boolean",
      "description": "When true, this function is exposed to agents in this app as a tool. Agents must still list its name under their graph_spec.tools.functions[] to call it."
    },
    "description": {
      "type": "string",
      "description": "Function description"
    },
    "memoryLimitMb": {
      "type": "number",
      "description": "Memory limit in MB (default: 128)"
    },
    "agent_tool_mode": {
      "enum": [
        "read_only",
        "read_write"
      ],
      "type": "string",
      "description": "read_only (default) | read_write. read_write tools require human approval per call (HITL)."
    },
    "agent_tool_exposed_to": {
      "enum": [
        "developer_only",
        "end_user"
      ],
      "type": "string",
      "description": "developer_only (default) — only dashboard/CLI test runs can call it. end_user — also callable by public agent invocations."
    },
    "agent_tool_description": {
      "type": "string",
      "maxLength": 500,
      "description": "Short imperative description shown to the LLM (max 500 chars). Required for any function the model is expected to choose intelligently."
    },
    "allow_service_key_impersonation": {
      "type": "boolean",
      "description": "Default true. Lets an app-scoped service-key caller assert \"act as user X\" via the X-Butterbase-As-User header — the runtime populates ctx.user with the asserted id before invoking. Set to false on admin-only or billing-webhook handlers that must never accept an as-user assertion: control-api will 403 such calls at the edge."
    }
  },
  "additionalProperties": false
}

What this tool wraps· 5 endpoints

min confidence0.700.50

Parent server

io.github.butterbase-ai/mcp

https://github.com/butterbase-ai/butterbase-oss

1/7 registries
View full server →
deploy_function — io.github.butterbase-ai/mcp — PRSM MCP