@@ -296,12 +296,146 @@ def row(label: str, value: Any) -> str:
296296
297297 <footer>
298298 Generated at { esc (data ["timestamp" ])} ·
299- <a href="?format=json">JSON</a>
299+ <a href="?format=json">JSON</a> ·
300+ <a href="/">Home</a>
300301 </footer>
301302</body>
302303</html>"""
303304
304305
306+ def _server_base_url (request : Request ) -> str :
307+ """Public base URL of this server: BASE_URL env if set, else derived
308+ from the incoming request (scheme://host[:port])."""
309+ configured = os .getenv ("BASE_URL" , "" ).rstrip ("/" )
310+ if configured :
311+ return configured
312+ return f"{ request .url .scheme } ://{ request .url .netloc } "
313+
314+
315+ def _render_index_html (request : Request ) -> str :
316+ esc = _html .escape
317+ base_url = _server_base_url (request )
318+ mcp_url = f"{ base_url } /mcp"
319+
320+ auth_enabled = os .getenv ("ENABLE_OAUTH" , "false" ).lower () == "true"
321+ auth_provider = os .getenv ("AUTH_PROVIDER" , "none" ) if auth_enabled else "none"
322+ if auth_enabled :
323+ auth_note = (
324+ f"OAuth 2.1 is required (provider: <code>{ esc (auth_provider )} </code>). "
325+ "MCP clients that support OAuth will be redirected to log in automatically."
326+ )
327+ else :
328+ auth_note = "No authentication is required to connect (development mode)."
329+
330+ obp_base_url = os .getenv ("OBP_BASE_URL" , "" ).rstrip ("/" )
331+ obp_line = (
332+ f'<p>This server fronts the Open Bank Project API at <a href="{ esc (obp_base_url )} ">{ esc (obp_base_url )} </a>.</p>'
333+ if obp_base_url
334+ else ""
335+ )
336+
337+ claude_code_cmd = f"claude mcp add --transport http obp { mcp_url } "
338+ vscode_json = f"""{{
339+ "servers": {{
340+ "obp": {{
341+ "type": "http",
342+ "url": "{ mcp_url } "
343+ }}
344+ }}
345+ }}"""
346+ mcp_remote_json = f"""{{
347+ "mcpServers": {{
348+ "obp": {{
349+ "command": "npx",
350+ "args": ["-y", "mcp-remote", "{ mcp_url } "]
351+ }}
352+ }}
353+ }}"""
354+
355+ return f"""<!doctype html>
356+ <html lang="en">
357+ <head>
358+ <meta charset="utf-8">
359+ <title>OBP-MCP — Open Bank Project MCP Server</title>
360+ <meta name="viewport" content="width=device-width,initial-scale=1">
361+ <style>
362+ :root {{ color-scheme: light dark; }}
363+ body {{ font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
364+ max-width: 900px; margin: 2rem auto; padding: 0 1rem; }}
365+ h1 {{ margin-bottom: 0; }}
366+ .sub {{ color: #888; font-size: 0.9em; margin-top: 0.25rem; }}
367+ section {{ margin: 1.5rem 0; padding: 1rem; border: 1px solid #8884; border-radius: 6px; }}
368+ section h2 {{ margin: 0 0 0.75rem; font-size: 1.1em; }}
369+ section h3 {{ margin: 1rem 0 0.5rem; font-size: 1em; }}
370+ pre {{ background: #8881; padding: 0.75rem; border-radius: 6px; overflow-x: auto;
371+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; }}
372+ code {{ font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background: #8881;
373+ padding: 0.1em 0.3em; border-radius: 4px; }}
374+ pre code {{ background: none; padding: 0; }}
375+ .endpoint {{ font-size: 1.05em; }}
376+ ul {{ padding-left: 1.25rem; }}
377+ footer {{ margin: 2rem 0 1rem; color: #888; font-size: 0.85em; }}
378+ </style>
379+ </head>
380+ <body>
381+ <h1>Open Bank Project MCP Server</h1>
382+ <p class="sub">Model Context Protocol access to the Open Bank Project API</p>
383+
384+ <section>
385+ <h2>MCP endpoint</h2>
386+ <p class="endpoint"><code>{ esc (mcp_url )} </code> (Streamable HTTP)</p>
387+ <p>{ auth_note } </p>
388+ { obp_line }
389+ </section>
390+
391+ <section>
392+ <h2>Connect</h2>
393+
394+ <h3>Claude Code</h3>
395+ <pre><code>{ esc (claude_code_cmd )} </code></pre>
396+
397+ <h3>Claude.ai / Claude Desktop (custom connector)</h3>
398+ <p>Add a custom connector in Settings → Connectors with the URL <code>{ esc (mcp_url )} </code>.</p>
399+
400+ <h3>VS Code (<code>mcp.json</code>)</h3>
401+ <pre><code>{ esc (vscode_json )} </code></pre>
402+
403+ <h3>Clients without native remote MCP support (via <code>mcp-remote</code>)</h3>
404+ <pre><code>{ esc (mcp_remote_json )} </code></pre>
405+ </section>
406+
407+ <section>
408+ <h2>What you get</h2>
409+ <ul>
410+ <li><code>list_endpoints_by_tag</code> / <code>list_all_endpoint_tags</code> — discover OBP API endpoints by tag</li>
411+ <li><code>get_endpoint_schema</code> — full request/response schema for an endpoint</li>
412+ <li><code>call_obp_api</code> — execute calls against the OBP API</li>
413+ <li><code>list_glossary_terms</code> / <code>get_glossary_term</code> — 800+ banking and OBP glossary terms</li>
414+ </ul>
415+ </section>
416+
417+ <section>
418+ <h2>Diagnostics</h2>
419+ <ul>
420+ <li><a href="/status">Status page</a> — configuration, connectivity checks, index freshness (<a href="/status?format=json">JSON</a>)</li>
421+ <li><a href="/health">Health</a> — liveness probe</li>
422+ <li><a href="/ready">Ready</a> — readiness probe</li>
423+ </ul>
424+ </section>
425+
426+ <footer>
427+ <a href="https://github.com/OpenBankProject/OBP-MCP">OBP-MCP</a> ·
428+ <a href="https://www.openbankproject.com/">Open Bank Project</a>
429+ </footer>
430+ </body>
431+ </html>"""
432+
433+
434+ async def index_endpoint (request : Request ) -> Response :
435+ """Public index page: connectivity instructions and links to diagnostics."""
436+ return HTMLResponse (_render_index_html (request ))
437+
438+
305439async def health_endpoint (request : Request ) -> Response :
306440 """Liveness probe. Returns 200 as long as the process is serving HTTP.
307441 Makes no outbound calls and touches no indexes — safe to poll frequently.
0 commit comments