Skip to main content
Glama

Remote MCP Server

app.ts3.23 kB
import { Hono } from "hono"; import { layout, homeContent, parseApproveFormBody, renderAuthorizationRejectedContent, renderAuthorizationApprovedContent, renderLoggedInAuthorizeScreen, renderLoggedOutAuthorizeScreen, } from "./utils"; import type { OAuthHelpers } from "@cloudflare/workers-oauth-provider"; export type Bindings = Env & { OAUTH_PROVIDER: OAuthHelpers; }; const app = new Hono<{ Bindings: Bindings; }>(); // Render a basic homepage placeholder to make sure the app is up app.get("/", async (c) => { const content = await homeContent(c.req.raw); return c.html(layout(content, "MCP Remote Auth Demo - Home")); }); // Render an authorization page // If the user is logged in, we'll show a form to approve the appropriate scopes // If the user is not logged in, we'll show a form to both login and approve the scopes app.get("/authorize", async (c) => { // We don't have an actual auth system, so to demonstrate both paths, you can // hard-code whether the user is logged in or not. We'll default to true // const isLoggedIn = false; const isLoggedIn = true; const oauthReqInfo = await c.env.OAUTH_PROVIDER.parseAuthRequest(c.req.raw); const oauthScopes = [ { name: "read_profile", description: "Read your basic profile information", }, { name: "read_data", description: "Access your stored data" }, { name: "write_data", description: "Create and modify your data" }, ]; if (isLoggedIn) { const content = await renderLoggedInAuthorizeScreen(oauthScopes, oauthReqInfo); return c.html(layout(content, "MCP Remote Auth Demo - Authorization")); } const content = await renderLoggedOutAuthorizeScreen(oauthScopes, oauthReqInfo); return c.html(layout(content, "MCP Remote Auth Demo - Authorization")); }); // The /authorize page has a form that will POST to /approve // This endpoint is responsible for validating any login information and // then completing the authorization request with the OAUTH_PROVIDER app.post("/approve", async (c) => { const { action, oauthReqInfo, email, password } = await parseApproveFormBody( await c.req.parseBody(), ); if (!oauthReqInfo) { return c.html("INVALID LOGIN", 401); } // If the user needs to both login and approve, we should validate the login first if (action === "login_approve") { // We'll allow any values for email and password for this demo // but you could validate them here // Ex: // if (email !== "user@example.com" || password !== "password") { // biome-ignore lint/correctness/noConstantCondition: This is a demo if (false) { return c.html( layout( await renderAuthorizationRejectedContent("/"), "MCP Remote Auth Demo - Authorization Status", ), ); } } // The user must be successfully logged in and have approved the scopes, so we // can complete the authorization request const { redirectTo } = await c.env.OAUTH_PROVIDER.completeAuthorization({ request: oauthReqInfo, userId: email, metadata: { label: "Test User", }, scope: oauthReqInfo.scope, props: { userEmail: email, }, }); return c.html( layout( await renderAuthorizationApprovedContent(redirectTo), "MCP Remote Auth Demo - Authorization Status", ), ); }); 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/Cam10001110101/remote-mcp-server'

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