Skip to main content

Overview

ChatGPT can connect to your MCP servers to access custom tools and capabilities. This integration allows ChatGPT to leverage your MCP tools during conversations, extending its functionality beyond built-in capabilities.
MCP server integration with ChatGPT requires a deployed server accessible via HTTPS. You cannot use localhost URLs.

Prerequisites

1

Deployed MCP Server

Your MCP server must be deployed and accessible via HTTPS:
  • Manufact Cloud: Automatic HTTPS deployment
  • Self-hosted: Requires SSL certificate (Let’s Encrypt recommended)
  • Custom domain: Optional but recommended
2

ChatGPT Plus or Enterprise

MCP integration requires:
  • ChatGPT Plus subscription, or
  • ChatGPT Enterprise account, or
  • ChatGPT Team account
3

Server URL

Know your MCP server endpoint URL:
https://your-server.run.mcp-use.com/mcp

Connection Methods

Custom Actions allow you to create reusable connections to your MCP server that can be used across multiple ChatGPT sessions.
1

Get MCP Server Metadata

First, retrieve your server’s tool definitions:
curl https://your-server.run.mcp-use.com/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "id": 1
  }'
This returns your server’s available tools and their schemas.
2

Create Custom GPT

  1. Go to ChatGPT
  2. Click your profile icon → My GPTs
  3. Click Create a GPT
  4. In the Configure tab, click Create new action
3

Configure Action Schema

Create an OpenAPI schema for your MCP tools:
openapi: 3.0.0
info:
  title: My MCP Server
  version: 1.0.0
  description: Custom tools from my MCP server
servers:
  - url: https://your-server.run.mcp-use.com
paths:
  /mcp:
    post:
      operationId: callMCPTool
      summary: Call an MCP tool
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                jsonrpc:
                  type: string
                  default: "2.0"
                method:
                  type: string
                  enum: [tools/call]
                params:
                  type: object
                  properties:
                    name:
                      type: string
                      description: Tool name to call
                    arguments:
                      type: object
                      description: Tool arguments
                id:
                  type: integer
      responses:
        '200':
          description: Tool result
4

Test and Save

  1. Test the action in ChatGPT’s action editor
  2. Save your Custom GPT
  3. Start using your MCP tools in conversations

Method 2: Direct Tool Calling

ChatGPT can call HTTP endpoints directly using its function calling capabilities:
1

Describe Your Tools

In your ChatGPT conversation, describe your MCP server’s capabilities:
I have an MCP server at https://your-server.run.mcp-use.com/mcp
that provides the following tools:

1. get_weather: Gets weather for a location
   - Input: { "city": "string" }

2. search_web: Searches the web
   - Input: { "query": "string" }

Please use these tools when relevant.
2

ChatGPT Makes Requests

ChatGPT will format and send MCP-compatible requests:
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "city": "Tokyo"
    }
  },
  "id": 1
}

Server Configuration

CORS Configuration

Ensure your MCP server allows requests from ChatGPT:
import { MCPServer } from "mcp-use/server";

const server = new MCPServer({
  name: "my-server",
  version: "1.0.0",
  cors: {
    origin: [
      "https://chat.openai.com",
      "https://chatgpt.com"
    ],
    credentials: true
  }
});

Authentication

Implement API key validation:
import { MCPServer } from "mcp-use/server";

const server = new MCPServer({
  name: "my-server",
  version: "1.0.0",
  middleware: [
    (req, res, next) => {
      const apiKey = req.headers["x-api-key"];
      if (apiKey !== process.env.EXPECTED_API_KEY) {
        return res.status(401).json({ error: "Unauthorized" });
      }
      next();
    }
  ]
});
In ChatGPT Custom Action, add header:
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
security:
  - ApiKeyAuth: []

Example Integration

Weather Tool Integration

1

Create MCP Server

import { MCPServer, text } from "mcp-use/server";
import { z } from "zod";

const server = new MCPServer({
  name: "weather-server",
  version: "1.0.0"
});

server.tool({
  name: "get_weather",
  description: "Get current weather for a city",
  schema: z.object({
    city: z.string().describe("City name"),
    units: z.enum(["celsius", "fahrenheit"]).optional()
  })
}, async ({ city, units = "celsius" }) => {
  const weather = await fetchWeather(city, units);
  return text(`Weather in ${city}: ${weather.temp}°, ${weather.conditions}`);
});

await server.listen(3000);
2

Deploy Server

# Deploy to Manufact Cloud
npx mcp-use deploy

# Note the deployment URL
# Example: https://weather-abc123.run.mcp-use.com/mcp
3

Create Custom GPT

Configure action in ChatGPT:
openapi: 3.0.0
info:
  title: Weather Server
  version: 1.0.0
servers:
  - url: https://weather-abc123.run.mcp-use.com
paths:
  /mcp:
    post:
      operationId: getWeather
      summary: Get weather for a city
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                jsonrpc:
                  type: string
                  default: "2.0"
                method:
                  type: string
                  enum: [tools/call]
                params:
                  type: object
                  properties:
                    name:
                      type: string
                      enum: [get_weather]
                    arguments:
                      type: object
                      properties:
                        city:
                          type: string
                        units:
                          type: string
                          enum: [celsius, fahrenheit]
4

Test in ChatGPT

Start a conversation:
User: What's the weather in Tokyo?

ChatGPT: [Calls your MCP tool]
Let me check the weather in Tokyo for you.

[Displays weather information from your server]

Advanced Features

Streaming Responses

Enable streaming for long-running operations:
import { MCPServer, streamText } from "mcp-use/server";

server.tool({
  name: "generate_report",
  description: "Generate a detailed report",
  schema: z.object({ topic: z.string() })
}, async function* ({ topic }) {
  yield* streamText(`Generating report on ${topic}...\n\n`);
  
  for (const section of generateSections(topic)) {
    yield* streamText(section + "\n");
    await delay(100);
  }
});

Error Handling

Provide helpful error messages:
server.tool({
  name: "search_database",
  description: "Search internal database",
  schema: z.object({ query: z.string() })
}, async ({ query }) => {
  try {
    const results = await database.search(query);
    return text(`Found ${results.length} results`);
  } catch (error) {
    if (error.code === "RATE_LIMIT") {
      return text("Rate limit exceeded. Please try again in a few minutes.");
    }
    throw error; // Let MCP handle other errors
  }
});

Tool Context

Provide context-aware responses:
server.tool({
  name: "get_user_info",
  description: "Get information about the current user",
  schema: z.object({})
}, async ({}, context) => {
  // Access user information from context
  const userId = context.headers["x-user-id"];
  const userInfo = await fetchUserInfo(userId);
  
  return text(`User: ${userInfo.name}, Email: ${userInfo.email}`);
});

Testing Your Integration

Test with Inspector

# Open inspector
open https://inspector.mcp-use.com/inspector?autoConnect=https://your-server.run.mcp-use.com/mcp
Test tools manually before integrating with ChatGPT.

Test with cURL

# List tools
curl -X POST https://your-server.run.mcp-use.com/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "id": 1
  }'

# Call tool
curl -X POST https://your-server.run.mcp-use.com/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "get_weather",
      "arguments": {"city": "Tokyo"}
    },
    "id": 2
  }'

Troubleshooting

Problem: ChatGPT cannot access your server due to CORSSolution:
const server = new MCPServer({
  cors: {
    origin: [
      "https://chat.openai.com",
      "https://chatgpt.com"
    ],
    methods: ["GET", "POST", "OPTIONS"],
    credentials: true
  }
});
Problem: API key or OAuth not workingSolution:
  • Verify API key is correctly set in ChatGPT action headers
  • Check server logs for authentication errors
  • Test authentication with cURL first
  • Ensure OAuth callback URL is whitelisted
Problem: ChatGPT receives “tool not found” errorSolution:
  • Verify tool name matches exactly
  • Check tool is registered: tools/list
  • Ensure server is deployed and running
  • Test with Inspector first
Problem: Requests timeoutSolution:
  • Optimize slow operations
  • Implement streaming for long tasks
  • Increase server timeout settings
  • Check network connectivity

Best Practices

Use descriptive tool names that clearly indicate their purpose
Provide detailed descriptions in tool schemas to help ChatGPT understand when to use them
Implement proper authentication for production deployments
Handle errors gracefully with helpful error messages
Test thoroughly before deploying to production
Monitor usage with logging and analytics
Set rate limits to prevent abuse
Use HTTPS for all production deployments

Rate Limiting

Implement rate limiting to control usage:
import rateLimit from "express-rate-limit";

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // Limit each IP to 100 requests per windowMs
  message: "Too many requests, please try again later."
});

const server = new MCPServer({
  name: "rate-limited-server",
  middleware: [limiter]
});

Usage Analytics

Track tool usage:
server.tool({
  name: "track_usage",
  description: "Internal tracking tool"
}, async (args, context) => {
  // Log usage to analytics
  await analytics.track({
    event: "tool_called",
    toolName: context.tool.name,
    userId: context.userId,
    timestamp: new Date()
  });
  
  // Continue with tool logic
});

Next Steps

Integrate with Claude

Connect to Claude Desktop

Custom Clients

Build custom MCP clients

Authentication

Secure your integration

Monitoring

Track usage and performance

Build docs developers (and LLMs) love