ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop using the Portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingMCP - Quick start
    Develop Locally
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth
Concepts
Development
Policies
Handlers
API Keys
MCP Server
    IntroductionToolsPromptsResourcesTestingGraphQLCustom ToolsOpenAI Apps SDK
    Guides
MCP Gateway
AI Gateway
Developer Portal
Monetization
Deploying & Source Control
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsSecuritySupportTrust & ComplianceChangelog
powered by Zudoku
MCP Server

MCP Server With OpenAI Apps SDK

The OpenAI Apps SDK is an integration of MCP that lets you expose applications to ChatGPT. Zuplo's MCP Server provides built-in support for the Apps SDK through tools, resources, and the ZuploMcpSdk class, which allows you to optionally access incoming request metadata and set response metadata required for ChatGPT widget rendering.

This page covers the MCP Server handler, which turns your own OpenAPI routes into an MCP server. If you're proxying to upstream MCP servers (Linear, Stripe, Notion, internal services, etc.) through Zuplo's MCP Gateway, Apps SDK UI surfaces pass through the gateway as ordinary MCP resources — no extra configuration is required on the gateway side. Build the Apps SDK app on whichever MCP server emits the UI.

The OpenAI Apps SDK and support for it in Zuplo's mcpServerHandler is in beta and subject to change!

tools

MCP tools define the functionality of your app. Zuplo MCP servers support tools for the OpenAI Apps SDK with _meta metadata through the x-zuplo-route.mcp configuration. Learn more about configuration options for tools in the MCP Server Tools documentation.

resources

MCP resources are how your app's sandboxed widgets are displayed in the chat interface. Zuplo MCP servers support resources for the OpenAI Apps SDK with _meta metadata through the x-zuplo-route.mcp configuration. Learn more about configuration options for resources in the MCP Server Resources documentation.

Configuring metadata

When configuring and describing your tools and resources, you may need to set specific annotations and static _meta for when ChatGPT inspects these entities. _meta is the main way that the OpenAI Apps SDK interfaces with an MCP server. For example, an application may want to set a readOnlyHint annotation on a tool and define that the tool renders a component for your application with the static _meta["openai/outputTemplate"] metadata:

Code
"x-zuplo-route": { "corsPolicy": "none", "handler": { "export": "default", "module": "$import(./modules/weather)" }, "mcp": { "type": "tool", "name": "get_current_weather", "description": "Retrieve and render application weather component", "annotations": { "readOnlyHint": true }, "_meta": { "openai/toolInvocation/invoking": "Getting weather ...", "openai/toolInvocation/invoked": "Weather ready!", "openai/outputTemplate": "ui://widget/weather.html" } } }

The resource defined at ui://widget/weather.html can then be used to render the app. Learn more about this in the Zuplo MCP Server Tools documentation, the OpenAI Apps SDK documentation for defining tools and the OpenAI Apps SDK documentation for setting up tools and resources.

ZuploMcpSdk

The ZuploMcpSdk class in the @zuplo/runtime provides methods to interact with an MCP request and response metadata, which is essential for building ChatGPT Apps that return structuredContent and _meta payloads out of band of the typical API response flow.

This means that you can still use your existing APIs as MCP tools for your OpenAI Apps SDK application while wrapping them with a custom module that uses ZuploMcpSdk in order to propagate _meta application state.

Usage

Import the SDK and create an instance in your custom handler by passing in the request context:

Code
import { ZuploContext, ZuploMcpSdk, ZuploRequest } from "@zuplo/runtime"; export default async function handler( request: ZuploRequest, context: ZuploContext, ) { const sdk = new ZuploMcpSdk(context); // Access the incoming MCP request metadata const mcpRequest = sdk.getRawCallToolRequest(); console.log(`Incoming _meta: ${JSON.stringify(mcpRequest?.params._meta)}`); // Invoke another route on the gateway and get data for the application const response = await context.invokeRoute("/v1/api/data"); const data = await response.json(); // Set metadata on the response for the ChatGPT widget sdk.setRawCallToolResult({ content: [{ type: "text", text: "Data retrieved" }], _meta: { applicationState: data, timestamp: new Date().toISOString(), }, }); return data; }

context.invokeRoute keeps the new request within the gateway: it does not go back out to HTTP. But it's important to keep in mind that an invoked route on the gateway will re-invoke the inbound and outbound policy pipeline for the invoked route!

Methods

getRawCallToolRequest()

Retrieves the raw MCP tools/call request object, including any _meta sent by ChatGPT. Use this to access client context hints like locale or user agent.

Code
const mcpRequest = sdk.getRawCallToolRequest(); const locale = mcpRequest?.params._meta?.["openai/locale"];

setRawCallToolResult(result)

Sets the MCP tool result, including the _meta field that is sent to the ChatGPT widget but not visible to the model. Use this to pass data that your widget needs for rendering.

Code
sdk.setRawCallToolResult({ content: [{ type: "text", text: "Operation complete" }], _meta: { detailedData: largeDataObject, lastSyncedAt: new Date().toISOString(), }, });

For complete documentation on building ChatGPT Apps, see the OpenAI Apps SDK documentation and the OpenAI Apps SDK guide on setting up your MCP server

Edit this page
Last modified on May 27, 2026
Custom ToolsAuth0 Setup
On this page
  • tools
  • resources
  • Configuring metadata
  • ZuploMcpSdk
    • Usage
    • Methods
JSON
TypeScript
TypeScript
TypeScript