Skip to main content
Glama

Linear Streamable MCP Server

by iceener
discovery.ts3.98 kB
import type { HttpBindings } from '@hono/node-server'; import { Hono } from 'hono'; import { config } from '../../config/env.ts'; export function discoveryRoutes() { const app = new Hono<{ Bindings: HttpBindings }>(); if (config.AUTH_ENABLED) { app.get('/.well-known/oauth-protected-resource', (c) => { const here = new URL(c.req.url); const authPort = Number(config.PORT) + 1; const defaultDiscovery = `${here.protocol}//${here.hostname}:${authPort}/.well-known/oauth-authorization-server`; const sid = here.searchParams.get('sid') ?? undefined; const resourceBase = `${here.protocol}//${here.host}/mcp`; const resourceUrl = (() => { try { if (!sid) { return resourceBase; } const u = new URL(resourceBase); u.searchParams.set('sid', sid); return u.toString(); } catch { return resourceBase; } })(); const metadata = { authorization_servers: [config.AUTH_DISCOVERY_URL || defaultDiscovery], resource: resourceUrl, } as const; return c.json(metadata); }); app.get('/mcp/.well-known/oauth-protected-resource', (c) => { const here = new URL(c.req.url); const authPort = Number(config.PORT) + 1; const defaultDiscovery = `${here.protocol}//${here.hostname}:${authPort}/.well-known/oauth-authorization-server`; const sid = here.searchParams.get('sid') ?? undefined; const resourceBase = `${here.protocol}//${here.host}/mcp`; const resourceUrl = (() => { try { if (!sid) { return resourceBase; } const u = new URL(resourceBase); u.searchParams.set('sid', sid); return u.toString(); } catch { return resourceBase; } })(); const metadata = { authorization_servers: [config.AUTH_DISCOVERY_URL || defaultDiscovery], resource: resourceUrl, } as const; return c.json(metadata); }); } app.get('/.well-known/oauth-authorization-server', (c) => { const here = new URL(c.req.url); const authPort = Number(config.PORT) + 1; const base = `${here.protocol}//${here.hostname}:${authPort}`; const metadata = { issuer: base, authorization_endpoint: config.OAUTH_AUTHORIZATION_URL || `${base}/authorize`, token_endpoint: config.OAUTH_TOKEN_URL || `${base}/token`, revocation_endpoint: config.OAUTH_REVOCATION_URL || `${base}/revoke`, registration_endpoint: `${base}/register`, response_types_supported: ['code'], grant_types_supported: [ 'authorization_code', 'refresh_token', 'client_credentials', ], code_challenge_methods_supported: ['S256'], token_endpoint_auth_methods_supported: ['client_secret_basic', 'none'], scopes_supported: (config.OAUTH_SCOPES || '').split(' ').filter(Boolean), } as const; return c.json(metadata); }); app.get('/mcp/.well-known/oauth-authorization-server', (c) => { const here = new URL(c.req.url); const authPort = Number(config.PORT) + 1; const base = `${here.protocol}//${here.hostname}:${authPort}`; const metadata = { issuer: base, authorization_endpoint: config.OAUTH_AUTHORIZATION_URL || `${base}/authorize`, token_endpoint: config.OAUTH_TOKEN_URL || `${base}/token`, revocation_endpoint: config.OAUTH_REVOCATION_URL || `${base}/revoke`, registration_endpoint: `${base}/register`, response_types_supported: ['code'], grant_types_supported: [ 'authorization_code', 'refresh_token', 'client_credentials', ], code_challenge_methods_supported: ['S256'], token_endpoint_auth_methods_supported: ['client_secret_basic', 'none'], scopes_supported: (config.OAUTH_SCOPES || '').split(' ').filter(Boolean), } as const; return c.json(metadata); }); return 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/iceener/linear-streamable-mcp-server'

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