tasq/node_modules/fastmcp/dist/examples/custom-routes.cjs.map

1 line
23 KiB
Plaintext

{"version":3,"sources":["/home/runner/work/fastmcp/fastmcp/dist/examples/custom-routes.cjs","../../src/examples/custom-routes.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fastmcp/fastmcp/dist/examples/custom-routes.cjs","sourcesContent":[null,"#!/usr/bin/env node\n\n/**\n * Example FastMCP server demonstrating custom HTTP routes using Hono's native API.\n *\n * This example shows how to:\n * - Use getApp() to access Hono's native API\n * - Add REST API endpoints with Hono's standard methods (app.get(), app.post(), etc.)\n * - Implement authentication with a custom helper function\n * - Handle file uploads\n * - Serve admin interfaces\n * - Create webhooks\n * - OAuth discovery endpoints\n * - Integrate custom routes with MCP tools\n *\n * Run with:\n * npx fastmcp dev src/examples/custom-routes.ts\n * npx fastmcp inspect src/examples/custom-routes.ts\n *\n * Or directly:\n * node dist/examples/custom-routes.js --transport=http-stream --port=8080\n */\n\nimport type { Context } from \"hono\";\n\nimport { z } from \"zod\";\n\nimport { FastMCP } from \"../FastMCP.js\";\n\n// Example in-memory data store\ninterface User {\n email: string;\n id: string;\n name: string;\n}\n\nconst users = new Map<string, User>([\n [\"1\", { email: \"alice@example.com\", id: \"1\", name: \"Alice\" }],\n [\"2\", { email: \"bob@example.com\", id: \"2\", name: \"Bob\" }],\n]);\n\nlet requestCount = 0;\n\n// Simple authentication for demonstration\ninterface UserAuth {\n [key: string]: unknown;\n role: string;\n userId: string;\n}\n\n// Create the FastMCP server with authentication\nconst server = new FastMCP<UserAuth>({\n // Simple authentication - in production, use proper tokens/JWTs\n authenticate: async (req) => {\n const authHeader = req.headers.authorization;\n if (authHeader === \"Bearer admin-token\") {\n return { role: \"admin\", userId: \"admin\" };\n } else if (authHeader === \"Bearer user-token\") {\n return { role: \"user\", userId: \"user1\" };\n }\n throw new Error(\"Invalid or missing authentication\");\n },\n name: \"custom-routes-example\",\n version: \"1.0.0\",\n});\n\n// Get the Hono app instance for direct access to Hono's native API\nconst app = server.getApp();\n\n// Helper to get authentication from Node.js request\nconst getAuth = async (c: Context): Promise<null | UserAuth> => {\n const req = c.env.incoming;\n const authHeader = req.headers.authorization;\n if (authHeader === \"Bearer admin-token\") {\n return { role: \"admin\", userId: \"admin\" };\n } else if (authHeader === \"Bearer user-token\") {\n return { role: \"user\", userId: \"user1\" };\n }\n return null;\n};\n\n// ===== PUBLIC ROUTES (No Authentication Required) =====\n\n// OAuth discovery endpoint - public by design\napp.get(\"/.well-known/openid-configuration\", async (c) => {\n return c.json({\n authorization_endpoint: \"https://example.com/oauth/authorize\",\n issuer: \"https://example.com\",\n jwks_uri: \"https://example.com/.well-known/jwks.json\",\n response_types_supported: [\"code\"],\n scopes_supported: [\"openid\", \"profile\", \"email\"],\n subject_types_supported: [\"public\"],\n token_endpoint: \"https://example.com/oauth/token\",\n });\n});\n\n// OAuth protected resource metadata - also public\napp.get(\"/.well-known/oauth-protected-resource\", async (c) => {\n return c.json({\n authorizationServers: [\"https://example.com\"],\n resource: \"https://example.com/api\",\n scopesSupported: [\"read\", \"write\"],\n });\n});\n\n// Public status endpoint - no auth needed\napp.get(\"/status\", async (c) => {\n return c.json({\n message: \"Server is running\",\n status: \"healthy\",\n timestamp: new Date().toISOString(),\n version: \"1.0.0\",\n });\n});\n\n// Public documentation endpoint\napp.get(\"/docs\", async (c) => {\n const html = `\n <!DOCTYPE html>\n <html>\n <head>\n <title>API Documentation</title>\n <style>\n body { font-family: sans-serif; margin: 40px; line-height: 1.6; }\n h1, h2 { color: #333; }\n .endpoint { background: #f8f9fa; padding: 15px; margin: 10px 0; border-left: 4px solid #007bff; }\n .method { font-weight: bold; color: #28a745; }\n .auth-required { color: #dc3545; font-size: 0.9em; }\n .public { color: #6c757d; font-size: 0.9em; }\n </style>\n </head>\n <body>\n <h1>Custom Routes API Documentation</h1>\n\n <h2>Public Endpoints (No Authentication)</h2>\n <div class=\"endpoint\">\n <span class=\"method\">GET</span> <code>/status</code>\n <div class=\"public\">✓ Public - Server health status</div>\n </div>\n <div class=\"endpoint\">\n <span class=\"method\">GET</span> <code>/.well-known/openid-configuration</code>\n <div class=\"public\">✓ Public - OAuth discovery</div>\n </div>\n\n <h2>Private Endpoints (Authentication Required)</h2>\n <div class=\"endpoint\">\n <span class=\"method\">GET</span> <code>/api/users</code>\n <div class=\"auth-required\">🔒 Requires: Bearer token</div>\n </div>\n <div class=\"endpoint\">\n <span class=\"method\">GET</span> <code>/admin</code>\n <div class=\"auth-required\">🔒 Requires: admin token</div>\n </div>\n\n <h2>Authentication</h2>\n <p>Use one of these tokens in the Authorization header:</p>\n <ul>\n <li><code>Bearer admin-token</code> - Admin access</li>\n <li><code>Bearer user-token</code> - User access</li>\n </ul>\n\n <h2>Examples</h2>\n <pre>\n# Public endpoint (no auth needed)\ncurl http://localhost:8080/status\n\n# Private endpoint (auth required)\ncurl -H \"Authorization: Bearer user-token\" http://localhost:8080/api/users\n </pre>\n </body>\n </html>\n `;\n return c.html(html);\n});\n\n// Public static assets\napp.get(\"/public/*\", async (c) => {\n // In a real app, you'd serve actual files here\n return c.json({\n file: c.req.url,\n message: \"This would serve static files\",\n public: true,\n });\n});\n\n// ===== PRIVATE ROUTES (Authentication Required) =====\n\n// Add custom routes for a REST API\napp.get(\"/api/users\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n const userList = Array.from(users.values());\n return c.json({\n authenticated_as: auth.userId,\n count: userList.length,\n role: auth.role,\n users: userList,\n });\n});\n\napp.get(\"/api/users/:id\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n const id = c.req.param(\"id\");\n const user = users.get(id);\n if (!user) {\n return c.json({ error: \"User not found\" }, 404);\n }\n return c.json(user);\n});\n\napp.post(\"/api/users\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n const body = (await c.req.json()) as { email: string; name: string };\n\n if (!body.name || !body.email) {\n return c.json({ error: \"Name and email are required\" }, 400);\n }\n\n const id = String(users.size + 1);\n const newUser: User = {\n email: body.email,\n id,\n name: body.name,\n };\n\n users.set(id, newUser);\n return c.json(newUser, 201);\n});\n\napp.put(\"/api/users/:id\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n const id = c.req.param(\"id\");\n const user = users.get(id);\n if (!user) {\n return c.json({ error: \"User not found\" }, 404);\n }\n\n const body = (await c.req.json()) as Partial<User>;\n const updatedUser = { ...user, ...body, id: user.id };\n users.set(user.id, updatedUser);\n return c.json(updatedUser);\n});\n\napp.delete(\"/api/users/:id\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n const id = c.req.param(\"id\");\n if (!users.has(id)) {\n return c.json({ error: \"User not found\" }, 404);\n }\n\n users.delete(id);\n return c.body(null, 204);\n});\n\n// Add a simple admin dashboard - requires admin role\napp.get(\"/admin\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n // Check for admin role\n if (auth.role !== \"admin\") {\n return c.json({ error: \"Admin access required\" }, 403);\n }\n\n const html = `\n <!DOCTYPE html>\n <html>\n <head>\n <title>Admin Dashboard</title>\n <style>\n body { font-family: sans-serif; margin: 40px; }\n h1 { color: #333; }\n .stats { background: #f0f0f0; padding: 20px; border-radius: 8px; }\n .stat { margin: 10px 0; }\n </style>\n </head>\n <body>\n <h1>Admin Dashboard</h1>\n <div class=\"stats\">\n <div class=\"stat\">Total Users: ${users.size}</div>\n <div class=\"stat\">Request Count: ${requestCount}</div>\n <div class=\"stat\">Server Time: ${new Date().toISOString()}</div>\n </div>\n <h2>Users</h2>\n <ul>\n ${Array.from(users.values())\n .map((u) => `<li>${u.name} (${u.email})</li>`)\n .join(\"\")}\n </ul>\n </body>\n </html>\n `;\n return c.html(html);\n});\n\n// Add a webhook endpoint\napp.post(\"/webhook/github\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n const payload = await c.req.json();\n const event = c.req.header(\"x-github-event\");\n\n console.log(`GitHub webhook received: ${event}`, payload);\n\n // Process webhook (e.g., trigger MCP tools)\n return c.json({ event, received: true });\n});\n\n// Add a file upload endpoint\napp.post(\"/upload\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n try {\n const body = await c.req.text();\n const size = Buffer.byteLength(body);\n\n return c.json({\n message: \"File received\",\n size: `${size} bytes`,\n });\n } catch (error) {\n return c.json(\n {\n error: error instanceof Error ? error.message : \"Upload failed\",\n },\n 500,\n );\n }\n});\n\n// Add middleware-like request counting\napp.get(\"/stats\", async (c) => {\n const auth = await getAuth(c);\n if (!auth) {\n return c.json({ error: \"Authentication required\" }, 401);\n }\n\n requestCount++;\n return c.json({\n requests: requestCount,\n timestamp: Date.now(),\n uptime: process.uptime(),\n });\n});\n\n// Add MCP tools that can interact with the custom routes\nserver.addTool({\n description: \"List all users from the REST API\",\n execute: async () => {\n const userList = Array.from(users.values());\n return {\n content: [\n {\n text: `Found ${userList.length} users:\\n${userList\n .map((u) => `- ${u.name} (${u.email})`)\n .join(\"\\n\")}`,\n type: \"text\",\n },\n ],\n };\n },\n name: \"list_users\",\n parameters: z.object({}),\n});\n\nserver.addTool({\n description: \"Create a new user via the REST API\",\n execute: async ({ email, name }) => {\n const id = String(users.size + 1);\n const newUser: User = { email, id, name };\n users.set(id, newUser);\n\n return {\n content: [\n {\n text: `User created successfully:\\nID: ${id}\\nName: ${name}\\nEmail: ${email}`,\n type: \"text\",\n },\n ],\n };\n },\n name: \"create_user\",\n parameters: z.object({\n email: z.string().email(),\n name: z.string(),\n }),\n});\n\nserver.addTool({\n description: \"Get server statistics\",\n execute: async () => {\n return {\n content: [\n {\n text: `Server Statistics:\n- Total Users: ${users.size}\n- Request Count: ${requestCount}\n- Uptime: ${Math.floor(process.uptime())} seconds\n- Memory Usage: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)} MB`,\n type: \"text\",\n },\n ],\n };\n },\n name: \"get_stats\",\n parameters: z.object({}),\n});\n\n// Add a resource that exposes the user list\nserver.addResource({\n description: \"Current user database\",\n load: async () => ({\n text: JSON.stringify(Array.from(users.values()), null, 2),\n }),\n mimeType: \"application/json\",\n name: \"user-database\",\n uri: \"resource://users\",\n});\n\n// Start the server\nconst PORT = process.env.FASTMCP_PORT\n ? parseInt(process.env.FASTMCP_PORT)\n : 8080;\n\nserver\n .start({\n httpStream: { port: PORT },\n transportType: \"httpStream\",\n })\n .then(() => {\n console.log(`\n🚀 Custom Routes Example Server Started!\n\nMCP Endpoint: http://localhost:${PORT}/mcp\nHealth Check: http://localhost:${PORT}/health\n\nPUBLIC ROUTES (No Authentication):\n- Status: http://localhost:${PORT}/status\n- Docs: http://localhost:${PORT}/docs\n- OAuth Config: http://localhost:${PORT}/.well-known/openid-configuration\n- Static Files: http://localhost:${PORT}/public/*\n\nPRIVATE ROUTES (Authentication Required):\n- REST API: http://localhost:${PORT}/api/users\n- Admin Panel: http://localhost:${PORT}/admin (admin only)\n- Statistics: http://localhost:${PORT}/stats\n- File Upload: http://localhost:${PORT}/upload\n- GitHub Hook: http://localhost:${PORT}/webhook/github\n\nAuthentication:\nUse \"Authorization: Bearer admin-token\" or \"Bearer user-token\"\n\nTry these commands:\n\n# Public routes (no auth needed)\ncurl http://localhost:${PORT}/status\ncurl http://localhost:${PORT}/docs\ncurl http://localhost:${PORT}/.well-known/openid-configuration\n\n# Private routes (auth required)\ncurl -H \"Authorization: Bearer user-token\" http://localhost:${PORT}/api/users\ncurl -H \"Authorization: Bearer admin-token\" http://localhost:${PORT}/admin\ncurl -X POST -H \"Authorization: Bearer user-token\" -H \"Content-Type: application/json\" \\\\\n -d '{\"name\":\"Charlie\",\"email\":\"charlie@example.com\"}' \\\\\n http://localhost:${PORT}/api/users\n\n# Test authentication failure\ncurl http://localhost:${PORT}/api/users # Should return 401\n\nMCP Tools available:\n- list_users\n- create_user \n- get_stats\n\nTest with MCP Inspector:\nnpx fastmcp inspect src/examples/custom-routes.ts\n `);\n })\n .catch((error) => {\n console.error(\"Failed to start server:\", error);\n process.exit(1);\n });\n"]}