jgtolentino/render-mcp-bridge
If you are the rightful owner of render-mcp-bridge and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
This document provides a comprehensive guide to deploying and integrating a Model Context Protocol (MCP) server using Render for ChatGPT.
Render MCP Bridge for ChatGPT
MCP (Model Context Protocol) HTTP/SSE server for ChatGPT integration, deployed on Render.
Architecture
ChatGPT ā https://mcp.pulser-ai.app (Squarespace DNS)
ā CNAME
https://<app-name>.onrender.com (Render)
ā
Express.js MCP Server (SSE + HTTP)
Features
- ā MCP Streamable-HTTP transport (official protocol)
- ā
ChatGPT Deep Research compatible (
search
+fetch
tools) - ā OpenAI Responses API compatible (all 6 tools)
- ā Health check endpoint for Render monitoring
- ā Initialize handler for proper MCP handshake
- ā Production-ready with Render Standard plan
Prerequisites
- Node.js 20+
- GitHub account
- Render account (free tier available)
- Squarespace DNS access
- ChatGPT Pro/Business/Enterprise (for custom MCP connectors)
š Quick Deploy
One-Click Deploy to Render
Click the button above to deploy directly to Render. The deployment will:
- Create a new Web Service automatically
- Install dependencies and start the server
- Provide a public HTTPS URL
For detailed deployment options and troubleshooting, see
Deployment Guide
Option A: One-Click Deploy (Fastest)
Use the button above for instant deployment.
Option B: Render Blueprint (Manual)
-
Repository is already on GitHub:
https://github.com/jgtolentino/render-mcp-bridge
-
Deploy via Render Blueprint
- Go to Render Dashboard
- Click New ā Blueprint
- Connect repository:
jgtolentino/render-mcp-bridge
- Render auto-detects
render.yaml
and provisions the service - Wait for deployment (check
/healthz
endpoint)
-
Note Your Render URL
- Format:
https://<app-name>.onrender.com
- Example:
https://mcp-server-abc123.onrender.com
- Format:
Option B: Manual Render Deployment
-
New Web Service
- Go to Render Dashboard
- Click New ā Web Service
- Connect GitHub repository
-
Configure Service
- Name:
mcp-server
- Environment: Node
- Build Command:
npm ci
- Start Command:
npm start
- Plan: Free
- Health Check Path:
/healthz
- Name:
-
Environment Variables
NODE_VERSION=20 NODE_ENV=production
-
Deploy
- Click Create Web Service
- Wait for build and health check to pass
DNS Configuration (Squarespace)
-
Login to Squarespace
-
Add CNAME Record
Type: CNAME Host: mcp Value: <your-app>.onrender.com TTL: 3600
Example:
mcp ā mcp-server-abc123.onrender.com
-
Wait for DNS Propagation
- Check:
dig mcp.pulser-ai.app CNAME
- Or: https://dnschecker.org/#CNAME/mcp.pulser-ai.app
- Usually takes 5-60 minutes
- Check:
-
Add Custom Domain in Render (Optional)
- In Render service settings ā Custom Domains
- Add
mcp.pulser-ai.app
- Render provisions free TLS certificate
Available Tools
Deep Research Tools (ChatGPT Compatible)
search(query: string)
- Search for documents or information by query
- Returns:
{results: [{id, title, url}]}
- Use case: ChatGPT Deep Research, knowledge retrieval
fetch(id: string)
- Retrieve complete document content by ID
- Returns:
{id, title, text, url, metadata}
- Use case: Full content retrieval for analysis and citation
General Purpose Tools (Responses API)
echo(message: string)
- Echo back the provided message
- Returns: Text content
get_time()
- Get current server time in UTC
- Returns: ISO timestamp with Unix time
status()
- Get server health information
- Returns: Uptime, memory, Node version, status
fetch_url(url: string)
- Fetch content from any HTTP/HTTPS URL
- Returns: HTTP status, content-type, response body (5KB limit)
Verification
1. Health Check
curl -sSf https://mcp-server-njax.onrender.com/healthz
# Expected: "ok"
2. Service Info
curl -sSf https://mcp-server-njax.onrender.com/
# Expected: JSON with service details
3. List Tools (MCP Protocol)
curl -X POST https://mcp-server-njax.onrender.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
# Expected: List of 6 tools
4. Test Search Tool
curl -X POST https://mcp-server-njax.onrender.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"search","arguments":{"query":"test"}},"id":2}'
# Expected: {"results":[...]} in content[0].text
5. Test Fetch Tool
curl -X POST https://mcp-server-njax.onrender.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"fetch","arguments":{"id":"doc-1"}},"id":3}'
# Expected: {id, title, text, url, metadata} in content[0].text
ChatGPT Integration
Enable Developer Mode
- ChatGPT ā Settings ā Connectors
- Enable Developer Mode
- Click Add Custom MCP
Connector Configuration
{
"name": "Pulser MCP",
"url": "https://mcp.pulser-ai.app",
"endpoints": {
"events": "/mcp/events",
"invoke": "/mcp/invoke"
},
"auth": {
"mode": "none"
}
}
Test in ChatGPT
- Start a new conversation
- Try: "Use the Pulser MCP to echo a message"
- ChatGPT should invoke your MCP server
Implementation Guide
Current State (Stub)
The server currently returns stubbed responses. Replace with real MCP tool handlers.
Example: Add Real Tools
Edit server.js
:
// Tool registry
const tools = {
echo: (params) => {
return { result: params };
},
get_time: () => {
return { result: new Date().toISOString() };
},
calculate: (params) => {
const { expression } = params;
try {
// Use a safe eval alternative like mathjs
const result = eval(expression); // UNSAFE - replace with mathjs
return { result };
} catch (error) {
return { error: error.message };
}
}
};
// Update /mcp/invoke handler
app.post('/mcp/invoke', (req, res) => {
const { tool, params } = req.body || {};
if (!tool || !tools[tool]) {
return res.status(400).json({
ok: false,
error: `Unknown tool: ${tool}`
});
}
try {
const result = tools[tool](params);
res.json({
ok: true,
tool,
...result
});
} catch (error) {
res.status(500).json({
ok: false,
error: error.message
});
}
});
MCP Tool Best Practices
-
Input Validation
- Validate all
params
before processing - Return clear error messages
- Validate all
-
Error Handling
- Catch and return errors gracefully
- Use appropriate HTTP status codes
-
Async Operations
- Use
async/await
for database/API calls - Implement timeouts
- Use
-
Security
- Sanitize inputs
- Rate limit requests
- Add authentication (OAuth) for production
Security Configuration
ChatGPT Responses API Compatibility
Important: This server is designed for use with OpenAI's ChatGPT Responses API, which handles authentication differently than traditional MCP servers.
How Authentication Works with ChatGPT
When you use this server with ChatGPT's Responses API, authentication is handled by OpenAI:
// In your API request to OpenAI (not to this MCP server)
{
"model": "gpt-5",
"tools": [{
"type": "mcp",
"server_url": "https://mcp-server-njax.onrender.com/mcp",
"authorization": "your-oauth-token-here", // <- OpenAI validates this
"require_approval": "never"
}]
}
Key Points:
- ā
OpenAI validates the
authorization
token in their API request - ā This MCP server does NOT receive or validate custom auth headers
- ā Custom HMAC/origin security is incompatible with ChatGPT Responses API
- ā For production: Use Render IP allow-list or environment-based restrictions
Production Security Options
Option 1: Render IP Allow-List (Recommended)
- Go to Render Dashboard ā Your Service ā Settings
- Add allowed IP ranges (e.g., OpenAI's IP blocks)
- Blocks all other traffic at infrastructure level
Option 2: Environment-Based Restrictions
# Set in Render Dashboard ā Environment
ALLOWED_API_KEYS=comma,separated,keys
# Then check in your server:
if (process.env.ALLOWED_API_KEYS) {
const apiKey = req.headers['x-api-key'];
if (!process.env.ALLOWED_API_KEYS.split(',').includes(apiKey)) {
return res.status(401).json({ error: 'Unauthorized' });
}
}
Why Not HMAC/Origin Security?
The server previously included HMAC signature and origin verification, but these are incompatible with ChatGPT Responses API:
- ā ChatGPT doesn't send
x-mcp-signature
headers - ā ChatGPT may not send
Origin
orReferer
headers - ā Custom authentication breaks MCP protocol compliance
Reference: OpenAI MCP Documentation
Monitoring & Debugging
Render Logs
# View live logs in Render dashboard
# Or use Render CLI
render logs -s mcp-server -f
Common Issues
Health Check Failing
- Check
/healthz
endpoint returns 200 - Verify server starts without errors
- Check Render build logs
DNS Not Resolving
- Wait up to 1 hour for propagation
- Verify CNAME record in Squarespace
- Use
dig mcp.pulser-ai.app
to check
ChatGPT Can't Connect
- Verify HTTPS works (not HTTP)
- Check CORS headers
- Test SSE endpoint manually
- Ensure ChatGPT plan supports custom connectors
SSE Connection Drops
- Check Render keeps connection alive
- Verify ping interval (15s recommended)
- Test with
curl -N
locally
Local Development
# Install dependencies
npm install
# Run locally
npm run dev
# Test endpoints
curl http://localhost:3000/healthz
curl -N http://localhost:3000/mcp/events
curl -X POST http://localhost:3000/mcp/invoke \
-H "Content-Type: application/json" \
-d '{"tool":"echo","params":{"x":1}}'
File Structure
render-mcp-bridge/
āāā server.js # Main Express server
āāā package.json # Dependencies and scripts
āāā render.yaml # Render blueprint config
āāā Dockerfile # Optional Docker build
āāā README.md # This file
āāā .gitignore # Git ignore patterns
Next Steps
- ā Deploy to Render
- ā Configure DNS
- ā Test ChatGPT integration
- ā³ Implement real MCP tools
- ā³ Add authentication
- ā³ Monitor and iterate
Resources
Support
For issues or questions:
- Create GitHub Issue
- Check Render status: https://status.render.com/
License
MIT