The problem
Most MCP (Model Context Protocol) servers only support stdio transport — you run them as a subprocess:
{
"mcpServers": {
"myserver": {
"command": "npx",
"args": ["-y", "my-mcp-server"]
}
}
}
But what if you want to expose your MCP server over HTTP? So that:
- Remote clients can connect without installing anything locally
- Multiple agents can share the same server instance
- You can deploy it on Vercel/Cloudflare/AWS Lambda
The MCP spec supports HTTP transport (SSE + JSON-RPC), but there's barely any documentation on how to implement it.
This post is the guide I wish I had when building MarketNow's MCP endpoint.
The architecture
Client (Claude Desktop, Cursor, etc.)
│
├── POST /api/mcp → JSON-RPC 2.0 request/response
│
└── GET /api/mcp → SSE stream (Server-Sent Events)
-
POST handles
initialize,tools/list,tools/call(JSON-RPC 2.0) - GET opens an SSE stream for server-to-client messages
The code (Vercel serverless function)
// api/mcp.js — Vercel serverless function
export default async function handler(req, res) {
// CORS
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') {
res.status(200).end();
return;
}
// GET → SSE stream
if (req.method === 'GET') {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
});
res.write(`data: ${JSON.stringify({ type: 'connected' })}\n\n`);
return;
}
// POST → JSON-RPC
if (req.method === 'POST') {
const { jsonrpc, id, method, params } = req.body;
let result;
switch (method) {
case 'initialize':
result = {
protocolVersion: '2024-11-05',
capabilities: { tools: {} },
serverInfo: { name: 'my-server', version: '1.0.0' },
};
break;
case 'tools/list':
result = {
tools: [{
name: 'hello',
description: 'Say hello',
inputSchema: { type: 'object', properties: { name: { type: 'string' } } },
}],
};
break;
case 'tools/call':
result = {
content: [{ type: 'text', text: `Hello, ${params.arguments.name}!` }],
};
break;
default:
res.status(200).json({
jsonrpc: '2.0', id,
error: { code: -32601, message: `Method not found: ${method}` },
});
return;
}
res.status(200).json({ jsonrpc: '2.0', id, result });
return;
}
res.status(405).json({ error: 'Method not allowed' });
}
The .well-known/mcp.json
Clients discover your MCP server via .well-known/mcp.json:
{
"name": "my-server",
"version": "1.0.0",
"transport": {
"type": "http+sse",
"http_url": "https://yourdomain.com/api/mcp",
"sse_url": "https://yourdomain.com/api/mcp"
},
"tools": [
{ "name": "hello", "description": "Say hello" }
]
}
Testing it
# Test initialize
curl -X POST https://yourdomain.com/api/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}'
# Test tools/list
curl -X POST https://yourdomain.com/api/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
# Test tools/call
curl -X POST https://yourdomain.com/api/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"hello","arguments":{"name":"World"}}}'
Deploy to Vercel
- Create
api/mcp.jsin your project - Deploy:
vercel --prod - Your MCP server is live at
https://yourproject.vercel.app/api/mcp
Why this matters
HTTP transport means:
- No installation required — clients connect via URL
- Multi-tenant — one server serves many agents
- Scalable — runs on serverless (Vercel, Cloudflare Workers, AWS Lambda)
- Stateless — each request is independent
This is how MarketNow works — one Vercel serverless function serves all MCP clients.
Try it
MarketNow's MCP endpoint is live:
curl -X POST https://marketnow.site/api/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Returns 4 tools: search_skills, get_skill, list_categories, health.
This post was written while building MarketNow — the trust layer for agent commerce. 8,764 MCP servers, each security-audited.
Top comments (0)