Skip to main content
Glama
joaquinsoza

Remote MCP Server on Cloudflare

by joaquinsoza
utils.ts7.2 kB
// Helper to generate the layout import { html, raw } from "hono/html"; import type { HtmlEscapedString } from "hono/utils/html"; import type { AuthRequest } from "@cloudflare/workers-oauth-provider"; // This file mainly exists as a dumping ground for uninteresting html and CSS // to remove clutter and noise from the auth logic. You likely do not need // anything from this file. export const layout = (content: HtmlEscapedString | string, title: string) => html` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>${title}</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body class="bg-gray-50 min-h-screen flex items-center justify-center"> <div class="max-w-2xl mx-auto p-8 text-center"> <h1 class="text-4xl font-bold text-gray-900 mb-4">X.com MCP Server Demo</h1> <p class="text-xl text-gray-600">A simple demonstration of the X.com API integration with MCP</p> </div> </body> </html> `; export const homeContent = async (req: Request): Promise<HtmlEscapedString> => { return html` <div class="text-center"> <h2 class="text-2xl font-semibold text-gray-800 mb-4">Available Endpoints</h2> <ul class="space-y-2 text-gray-600"> <li>GET /user/:username - Get user profile</li> <li>POST /tweet - Post a new tweet</li> <li>GET /search?q=query&count=10 - Search tweets</li> </ul> </div> `; }; export const renderLoggedInAuthorizeScreen = async ( oauthScopes: { name: string; description: string }[], oauthReqInfo: AuthRequest, ) => { return html` <div class="max-w-md mx-auto bg-white p-8 rounded-lg shadow-md"> <h1 class="text-2xl font-heading font-bold mb-6 text-gray-900"> Authorization Request </h1> <div class="mb-8"> <h2 class="text-lg font-semibold mb-3 text-gray-800"> MCP Remote Auth Demo would like permission to: </h2> <ul class="space-y-2"> ${oauthScopes.map( (scope) => html` <li class="flex items-start"> <span class="inline-block mr-2 mt-1 text-secondary" >✓</span > <div> <p class="font-medium">${scope.name}</p> <p class="text-gray-600 text-sm"> ${scope.description} </p> </div> </li> `, )} </ul> </div> <form action="/approve" method="POST" class="space-y-4"> <input type="hidden" name="oauthReqInfo" value="${JSON.stringify(oauthReqInfo)}" /> <input type="hidden" name="email" value="user@example.com" /> <button type="submit" name="action" value="approve" class="w-full py-3 px-4 bg-secondary text-white rounded-md font-medium hover:bg-secondary/90 transition-colors" > Approve </button> <button type="submit" name="action" value="reject" class="w-full py-3 px-4 border border-gray-300 text-gray-700 rounded-md font-medium hover:bg-gray-50 transition-colors" > Reject </button> </form> </div> `; }; export const renderLoggedOutAuthorizeScreen = async ( oauthScopes: { name: string; description: string }[], oauthReqInfo: AuthRequest, ) => { return html` <div class="max-w-md mx-auto bg-white p-8 rounded-lg shadow-md"> <h1 class="text-2xl font-heading font-bold mb-6 text-gray-900"> Authorization Request </h1> <div class="mb-8"> <h2 class="text-lg font-semibold mb-3 text-gray-800"> MCP Remote Auth Demo would like permission to: </h2> <ul class="space-y-2"> ${oauthScopes.map( (scope) => html` <li class="flex items-start"> <span class="inline-block mr-2 mt-1 text-secondary" >✓</span > <div> <p class="font-medium">${scope.name}</p> <p class="text-gray-600 text-sm"> ${scope.description} </p> </div> </li> `, )} </ul> </div> <form action="/approve" method="POST" class="space-y-4"> <input type="hidden" name="oauthReqInfo" value="${JSON.stringify(oauthReqInfo)}" /> <div class="space-y-4"> <div> <label for="email" class="block text-sm font-medium text-gray-700 mb-1" >Email</label > <input type="email" id="email" name="email" required class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary" /> </div> <div> <label for="password" class="block text-sm font-medium text-gray-700 mb-1" >Password</label > <input type="password" id="password" name="password" required class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary" /> </div> </div> <button type="submit" name="action" value="login_approve" class="w-full py-3 px-4 bg-primary text-white rounded-md font-medium hover:bg-primary/90 transition-colors" > Log in and Approve </button> <button type="submit" name="action" value="reject" class="w-full py-3 px-4 border border-gray-300 text-gray-700 rounded-md font-medium hover:bg-gray-50 transition-colors" > Reject </button> </form> </div> `; }; export const renderApproveContent = async ( message: string, status: string, redirectUrl: string, ) => { return html` <div class="max-w-md mx-auto bg-white p-8 rounded-lg shadow-md text-center" > <div class="mb-4"> <span class="inline-block p-3 ${ status === "success" ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800" } rounded-full" > ${status === "success" ? "✓" : "✗"} </span> </div> <h1 class="text-2xl font-heading font-bold mb-4 text-gray-900"> ${message} </h1> <p class="mb-8 text-gray-600"> You will be redirected back to the application shortly. </p> <a href="/" class="inline-block py-2 px-4 bg-primary text-white rounded-md font-medium hover:bg-primary/90 transition-colors" > Return to Home </a> ${raw(` <script> setTimeout(() => { window.location.href = "${redirectUrl}"; }, 2000); </script> `)} </div> `; }; export const renderAuthorizationApprovedContent = async (redirectUrl: string) => { return renderApproveContent("Authorization approved!", "success", redirectUrl); }; export const renderAuthorizationRejectedContent = async (redirectUrl: string) => { return renderApproveContent("Authorization rejected.", "error", redirectUrl); }; export const parseApproveFormBody = async (body: { [x: string]: string | File; }) => { const action = body.action as string; const email = body.email as string; const password = body.password as string; let oauthReqInfo: AuthRequest | null = null; try { oauthReqInfo = JSON.parse(body.oauthReqInfo as string) as AuthRequest; } catch (e) { oauthReqInfo = null; } return { action, oauthReqInfo, email, password }; };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/joaquinsoza/x-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server