Skip to main content
Glama

Remote MCP Server

by roboulos
app.ts4.36 kB
import { Hono } from "hono"; import { layout } from "./utils"; import type { OAuthHelpers } from "@cloudflare/workers-oauth-provider"; import type { Env } from "./types"; // Define app with the imported Env type const app = new Hono<{ Bindings: Env }>(); // Homepage - keep this for documentation app.get("/", async (c) => { return c.html(` <!DOCTYPE html> <html> <head> <title>Xano MCP Server</title> <style> body { font-family: system-ui, sans-serif; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px; } pre { background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; } code { background: #f4f4f4; padding: 2px 4px; border-radius: 4px; } </style> </head> <body> <h1>Xano MCP Server</h1> <h2>Connection Options</h2> <h3>1. Direct Token Authentication (For Web App)</h3> <p>Connect directly with your existing Xano token:</p> <pre><code>/sse?auth_token=YOUR_XANO_TOKEN&user_id=YOUR_USER_ID</code></pre> <h3>2. OAuth Flow (For External Clients)</h3> <p>Connect without a token to trigger the authentication flow:</p> <pre><code>/sse</code></pre> <h2>Using with Claude Desktop, Cursor, etc.</h2> <p>Use the <code>mcp-remote</code> proxy:</p> <pre><code>npx mcp-remote ${new URL("/sse", c.req.url).href}</code></pre> <p>Or with a direct token:</p> <pre><code>npx mcp-remote ${new URL("/sse", c.req.url).href}?auth_token=YOUR_XANO_TOKEN&user_id=YOUR_USER_ID</code></pre> </body> </html> `); }); // Simple health check endpoint app.get("/health", (c) => { return c.json({ status: "ok", message: "MCP server is running", version: "1.0.0", timestamp: new Date().toISOString() }); }); // Simple authorize endpoint that redirects to Xano login app.get("/authorize", async (c) => { const oauthReqInfo = await c.env.OAUTH_PROVIDER.parseAuthRequest(c.req.raw); if (!oauthReqInfo.clientId) { return c.text("Invalid request", 400); } // Store the state for callback const state = btoa(JSON.stringify(oauthReqInfo)); // Redirect to Xano login const redirectUri = `${c.env.XANO_BASE_URL}/auth/login?callback=${ encodeURIComponent(new URL("/callback", c.req.url).href) }&state=${encodeURIComponent(state)}`; return Response.redirect(redirectUri); }); // Callback handler for OAuth flow app.get("/callback", async (c) => { try { // Get state and token from query parameters const state = c.req.query("state"); const token = c.req.query("token"); const userId = c.req.query("user_id"); if (!state || !token || !userId) { return c.text("Missing required parameters", 400); } // Parse the state const oauthReqInfo = JSON.parse(atob(state)); if (!oauthReqInfo.clientId) { return c.text("Invalid state", 400); } // Complete the OAuth flow const { redirectTo } = await c.env.OAUTH_PROVIDER.completeAuthorization({ request: oauthReqInfo, userId: userId, metadata: {}, scope: [], // Replace with actual scopes/permissions if needed props: { accessToken: token, user: { id: userId } }, }); return Response.redirect(redirectTo); } catch (error) { console.error("Callback error:", error); return c.text("Authentication error", 500); } }); // Simple token endpoint required by OAuth spec app.post("/token", async (c) => { try { // Generate a token based on the code provided const tokenResponse = await c.env.OAUTH_PROVIDER.handleTokenRequest(c.req.raw); return new Response(tokenResponse.body, { status: tokenResponse.status, headers: tokenResponse.headers, }); } catch (error) { console.error("Token error:", error); return c.json({ error: "invalid_request" }, 400); } }); // Simple registration endpoint required by OAuth spec app.post("/register", async (c) => { // This is a minimal implementation const registrationResponse = await c.env.OAUTH_PROVIDER.handleRegistrationRequest(c.req.raw); return new Response(registrationResponse.body, { status: registrationResponse.status, headers: registrationResponse.headers, }); }); export default app;

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/roboulos/remote-mcp-server'

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