ICUICU
critical

@instantdb/mcp

v0.22.142

Model Context Protocol (MCP) server for managing Instant apps, schemas, and permissions!

npmGitHub ActionsFirst seen Feb 22, 2026

75

Total

16

Critical

39

High

20

Medium

Findings

unknown
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    106: 
    107: ```bash
>>> 108: cp .env.example .env
    109: ```
    110: 
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    109: ```
    110: 
>>> 111: Fill in all of the environment variables for your new `.env` file.
    112: 
    113: ```bash
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    117: Visit the server at [http://localhost:3123](http://localhost:3123).
    118: 
>>> 119: To work on the `stdio` version of the codebase, update your `.env` file with `SERVER_TYPE=stdio`.
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    197: 
    198:       const adminDb = init({
>>> 199:         appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,
    200:         adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,
    201:       });
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    198:       const adminDb = init({
    199:         appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,
>>> 200:         adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,
    201:       });
    202: 
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    237: 
    238:       const adminDb = init({
>>> 239:         appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,
    240:         adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,
    241:       });
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    238:       const adminDb = init({
    239:         appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,
>>> 240:         adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,
    241:       });
    242: 
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    336:         },
    337:     });
>>> 338:     const accessToken = token || process.env.INSTANT_ACCESS_TOKEN;
    339:     if (!accessToken) {
    340:         console.error('Provide an access token using --token or set INSTANT_ACCESS_TOKEN environment variable');
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    348: }
    349: function ensureEnv(key) {
>>> 350:     const v = process.env[key];
    351:     if (!v) {
    352:         throw new Error(`Missing environment variable ${key}`);
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    356: async function startSse() {
    357:     const honeycomb = new HoneycombSDK({
>>> 358:         apiKey: process.env.HONEYCOMB_API_KEY,
    359:         serviceName: 'mcp-server',
    360:     });
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    359:         serviceName: 'mcp-server',
    360:     });
>>> 361:     if (process.env.HONEYCOMB_API_KEY) {
    362:         honeycomb.start();
    363:     }
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    549:         res.status(200).send('Tip top!');
    550:     });
>>> 551:     const port = parseInt(process.env.PORT || '3123');
    552:     const host = process.env.IN_FLY ? '0.0.0.0' : 'localhost';
    553:     if (process.env.IN_FLY) {
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    550:     });
    551:     const port = parseInt(process.env.PORT || '3123');
>>> 552:     const host = process.env.IN_FLY ? '0.0.0.0' : 'localhost';
    553:     if (process.env.IN_FLY) {
    554:         app.set('trust proxy', 2);
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    551:     const port = parseInt(process.env.PORT || '3123');
    552:     const host = process.env.IN_FLY ? '0.0.0.0' : 'localhost';
>>> 553:     if (process.env.IN_FLY) {
    554:         app.set('trust proxy', 2);
    555:     }
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

    557: }
    558: async function main() {
>>> 559:     if (process.env.SERVER_TYPE === 'http') {
    560:         return startSse();
    561:     }
Report false positive
criticalDE-002Data ExfiltrationHigh ConfidenceLine 0

Environment file access

Detected by automated pattern matching (rule DE-002) with medium confidence. May be a false positive.

>>> 1: {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport 'dotenv/config';\nimport express, { Request, Response } from 'express';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { parseArgs } from 'node:util';\nimport version from './version.ts';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { HoneycombSDK } from '@honeycombio/opentelemetry-node';\nimport {\n  trace,\n  SpanKind,\n  SpanStatusCode,\n  Tracer,\n  Attributes,\n} from '@opentelemetry/api';\n\nimport {\n  createOAuthMetadata,\n  mcpAuthRouter,\n} from '@modelcontextprotocol/sdk/server/auth/router.js';\nimport { pinoHttp } from 'pino-http';\nimport { pino } from 'pino';\nimport { init } from '@instantdb/admin';\n\nimport schema from './db/instant.schema.ts';\nimport { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';\nimport {\n  addOAuthRoutes,\n  OAuthConfig,\n  ServiceProvider,\n  tokensOfBearerToken,\n} from './oauth-service-provider.ts';\nimport { KeyConfig } from './crypto.ts';\nimport indexHtml from './index.html.ts';\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\n\n// Helpers\n// -----------\nfunction createMCPServer(): McpServer {\n  return new McpServer({\n    name: '@instantdb/mcp',\n    version,\n  });\n}\n\n// Tool Registration\n// -----------\n\n// Adds tracing to server.tool\nfunction wrapServerWithTracing(\n  server: McpServer,\n  tracer: Tracer,\n  attrs: Attributes,\n): McpServer {\n  const originalTool = server.tool.bind(server);\n\n  server.tool = function (name: string, ...args: any[]): any {\n    // Find the callback (it's always the last argument)\n    const callback = args[args.length - 1];\n    const otherArgs = args.slice(0, -1);\n\n    // Wrap the callback with tracing\n    const wrappedCallback = async (...callbackArgs: any[]) => {\n      const span = tracer.startSpan(`tool.${name}`, {\n        attributes: attrs,\n      });\n      try {\n        const result = await callback(...callbackArgs);\n        span.setStatus({ code: SpanStatusCode.OK });\n        return result;\n      } catch (error) {\n        span.setStatus({ code: SpanStatusCode.ERROR });\n        span.recordException(error as Error);\n        throw error;\n      } finally {\n        span.end();\n      }\n    };\n\n    return originalTool(\n      name,\n      // @ts-expect-error: not sure how to type this\n      ...otherArgs,\n      wrappedCallback,\n    );\n  } as any;\n\n  return server;\n}\n\nfunction registerTools(server: McpServer) {\n  server.tool(\n    'learn',\n    \"If you don't have any context provided about InstantDB, use this tool to learn about it!\",\n    {},\n    async () => {\n      const instructions = `\n      You can learn about InstantDB by fetching our rules file for agents:\n\n      https://www.instantdb.com/llm-rules/AGENTS.md\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'get-schema',\n    'Fetch schema for an app by its ID!',\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      You can fetch the schema for the app by using the instant-cli tool:\n\n      \\`\\`\\`\n      npx instant-cli pull schema --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts. Now 'instant.schema.ts' with contain the schema for the app.\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'get-perms',\n    'Fetch permissions for an app by its ID',\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      You fetch the permissions for the app by using the instant-cli tool:\n\n      \\`\\`\\`\n      npx instant-cli pull perms --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts. Now 'instant.perms.ts' will contain the permissions for the app.\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'push-schema',\n    `Push local schema changes for an app to the server. Do this after updating your local 'instant.schema.ts' file.\n    If you don't have an instant.schema.ts file yet, use the get-schema tool to learn how to get this file.`,\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      Push schema changes by using the instant-cli tool:\n\n\n      \\`\\`\\`\n      npx instant-cli push schema --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts.\n\n      By default the instant-cli tool will assume new fields from the previous schema are additions and missing fields are deletions.\n      If you want to rename fields as part of your schema changes you can use the --rename flag to specify renames.\n\n      \\`\\`\\`\n      npx instant-cli push schema --app ${appId} --token ${adminToken} --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes\n      \\`\\`\\`\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'push-perms',\n    `Push local permissions changes for an app to the server. Do this after updating your local instant.perms.ts file.\n    If you don't have an instant.perms.ts file yet, use the get-perms tool to learn how to get this file.`,\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      Push permission changes by using the instant-cli tool:\n\n      \\`\\`\\`\n      npx instant-cli push schema --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts.\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'query',\n    'Execute a query againt an app. Useful for inspecting data in the app.',\n    {},\n    async () => {\n      const instructions = `\n      You can query data for an app by writing and executing a script using the\n      Admin SDK. Here's an example script for fetching a habit and its completions:\n\n      \\`\\`\\`typescript\n      import { init } from \"@instantdb/admin\";\n      import \"dotenv/config\";\n\n      const adminDb = init({\n        appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,\n        adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,\n      });\n\n      async function fetchHabit(habitName: string) {\n        const { habits } = await adminDb.query({\n          habits: {\n            $: { where: { name: habitName } },\n            completions: {},\n          },\n        });\n        console.log(habits);\n      }\n\n      fetchHabit(\"Read\");\n      \\`\\`\\`\n\n      If you're unsure how to write queries, refer to the documentation:\n\n      https://instantdb.com/docs/instaql.md\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'transact',\n    'Execute a transaction against an app. Useful for seeding or modifying data in the app.',\n    {},\n    async () => {\n      const instructions = `\n      You can transact data for an app by writing and executing a script using the\n      Admin SDK. Here's an example script for seeding a microblog app with some posts:\n\n      \\`\\`\\`typescript\n      import { init, id } from \"@instantdb/admin\";\n      import \"dotenv/config\";\n\n      const adminDb = init({\n        appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,\n        adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,\n      });\n\n      interface Post {\n        id: number;\n        author: string;\n        handle: string;\n        color: string;\n        content: string;\n        timestamp: string;\n        likes: number;\n        liked: boolean;\n      }\n\n      const mockPosts: Post[] = [\n        {\n          author: 'Sarah Chen',\n          handle: 'sarahchen',\n          color: 'bg-blue-100',\n          content: 'Just launched my new project! Really excited to share it with everyone.',\n          timestamp: '2h ago',\n          likes: 12,\n          liked: false,\n        },\n        {\n          author: 'Alex Rivera',\n          handle: 'alexrivera',\n          color: 'bg-purple-100',\n          content: 'Beautiful sunset today. Nature never stops amazing me.',\n          timestamp: '4h ago',\n          likes: 19,\n          liked: true,\n        },\n        {\n          author: 'Jordan Lee',\n          handle: 'jordanlee',\n          color: 'bg-pink-100',\n          content: 'Working on something cool with Next.js and TypeScript. Updates coming soon!',\n          timestamp: '6h ago',\n          likes: 7,\n          liked: false,\n        },\n      ];\n\n      function friendlyTimeToTimestamp(friendlyTime: string) {\n        const hours = parseInt(friendlyTime);\n        const now = Date.now();\n        return now - (hours * 60 * 60 * 1000);\n      }\n\n      function seed() {\n        console.log(\"Seeding db...\");\n        mockPosts.forEach(post => {\n          const userId = id();\n          const postId = id();\n          const user = adminDb.tx.$users[userId].create({});\n          const profile = adminDb.tx.profiles[userId].create({\n            displayName: post.author,\n            handle: post.handle,\n          }).link({ user: userId });\n          const postEntity = adminDb.tx.posts[postId].create({\n            color: post.color,\n            content: post.content,\n            timestamp: friendlyTimeToTimestamp(post.timestamp),\n          }).link({ author: userId });\n          const likes = Array.from({ length: post.likes }, () => adminDb.tx.likes[id()].create({ postId, userId }).link({ post: postId, user: userId }));\n          adminDb.transact([user, profile, postEntity, ...likes]);\n        })\n      }\n\n      seed();\n      \\`\\`\\`\n\n      If you're unsure how to make transactions, refer to the documentation:\n\n      https://instantdb.com/docs/instaml.md\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n}\n\nasync function startStdio() {\n  const {\n    values: { token, ['api-url']: apiUrl },\n  } = parseArgs({\n    options: {\n      token: {\n        type: 'string',\n      },\n      ['api-url']: {\n        type: 'string',\n      },\n    },\n  });\n\n  const accessToken = token || process.env.INSTANT_ACCESS_TOKEN;\n  if (!accessToken) {\n    console.error(\n      'Provide an access token using --token or set INSTANT_ACCESS_TOKEN environment variable',\n    );\n    process.exit(1);\n  }\n\n  const server = createMCPServer();\n  registerTools(server);\n\n  const transport = new StdioServerTransport();\n  await server.connect(transport);\n  console.error('Instant Platform MCP Server running on stdio');\n}\n\nfunction ensureEnv(key: string): string {\n  const v = process.env[key];\n  if (!v) {\n    throw new Error(`Missing environment variable ${key}`);\n  }\n  return v;\n}\n\nasync function startSse() {\n  const honeycomb = new HoneycombSDK({\n    apiKey: process.env.HONEYCOMB_API_KEY,\n    serviceName: 'mcp-server',\n  });\n\n  if (process.env.HONEYCOMB_API_KEY) {\n    honeycomb.start();\n  }\n\n  const tracer = trace.getTracer('mcp-server');\n\n  const db = init({\n    adminToken: ensureEnv('INSTANT_ADMIN_TOKEN'),\n    appId: ensureEnv('INSTANT_APP_ID'),\n    schema,\n    disableValidation: true,\n  });\n\n  const oauthConfig: OAuthConfig = {\n    clientId: ensureEnv('INSTANT_OAUTH_CLIENT_ID'),\n    clientSecret: ensureEnv('INSTANT_OAUTH_CLIENT_SECRET'),\n    serverOrigin: ensureEnv('SERVER_ORIGIN'),\n  };\n\n  const keyConfig: KeyConfig = JSON.parse(ensureEnv('INSTANT_AES_KEY'));\n\n  const app = express();\n  const logger = pino({ level: 'info' });\n\n  app.use((req, res, next) => {\n    const span = tracer.startSpan('http-req', {\n      kind: SpanKind.SERVER,\n      attributes: {\n        'http.method': req.method,\n        'http.url': req.url,\n        'http.target': req.path,\n        'http.host': req.get('host'),\n        'http.scheme': req.protocol,\n      },\n    });\n\n    const originalEnd = res.end.bind(res);\n    res.end = function (this: typeof res, ...args: any[]): typeof res {\n      span.setAttribute('http.status_code', res.statusCode);\n      span.setStatus({\n        code: res.statusCode >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK,\n      });\n      span.end();\n      return originalEnd(...args);\n    };\n\n    next();\n  });\n\n  app.use(\n    pinoHttp({\n      logger,\n      autoLogging: {\n        ignore(req) {\n          return req.url === '/health';\n        },\n      },\n    }),\n  );\n  app.use(express.json());\n\n  const proxyProvider = new ServiceProvider(db, oauthConfig, keyConfig);\n\n  const authRouterOptions = {\n    scopesSupported: ['apps-read', 'apps-write'],\n    provider: proxyProvider,\n    issuerUrl: new URL(oauthConfig.serverOrigin),\n    baseUrl: new URL(oauthConfig.serverOrigin),\n    serviceDocumentationUrl: new URL('https://instantdb.com/docs'),\n  };\n\n  const oauthMetadata = createOAuthMetadata(authRouterOptions);\n\n  app.use(mcpAuthRouter(authRouterOptions));\n\n  addOAuthRoutes(app, db, oauthConfig);\n\n  app.get('/.well-known/oauth-protected-resource/mcp', (_req, res) => {\n    res.json({\n      resource: `${oauthConfig.serverOrigin}/mcp`,\n      authorization_servers: [oauthMetadata.issuer],\n      scopes_supported: oauthMetadata.scopes_supported,\n      resource_documentation: 'https://instantdb.com/docs',\n    });\n  });\n\n  app.get('/.well-known/oauth-protected-resource/sse', (_req, res) => {\n    res.json({\n      resource: `${oauthConfig.serverOrigin}/mcp`,\n      authorization_servers: [oauthMetadata.issuer],\n      scopes_supported: oauthMetadata.scopes_supported,\n      resource_documentation: 'https://instantdb.com/docs',\n    });\n  });\n\n  const requireTokenMiddleware = (path: string) =>\n    requireBearerAuth({\n      verifier: proxyProvider,\n      resourceMetadataUrl: `${oauthConfig.serverOrigin}/.well-known/oauth-protected-resource/${path}`,\n    });\n\n  // Handle POST requests for client-to-server communication\n  app.post(\n    '/mcp',\n    requireTokenMiddleware('mcp'),\n    async (req: Request, res: Response) => {\n      const server = createMCPServer();\n      try {\n        const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n        wrapServerWithTracing(server, tracer, {\n          'client.client_id': tokens.mcpToken.client?.client_id,\n          'client.name': tokens.mcpToken.client?.client_name,\n          'client.id': tokens.mcpToken.client?.id,\n          'client.scope': tokens.mcpToken.client?.scope,\n          'client.uri': tokens.mcpToken.client?.client_uri,\n          'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n        });\n        registerTools(server);\n        const transport: StreamableHTTPServerTransport =\n          new StreamableHTTPServerTransport({\n            sessionIdGenerator: undefined,\n          });\n\n        req.on('close', () => {\n          transport.close();\n          server.close();\n        });\n        await server.connect(transport);\n        await transport.handleRequest(req, res, req.body);\n      } catch (e) {\n        console.error('Error handling MCP request:', e);\n        if (!res.headersSent) {\n          res.status(500).json({\n            jsonrpc: '2.0',\n            error: {\n              code: -32603,\n              message: 'Internal server error',\n            },\n            id: null,\n          });\n        }\n      }\n    },\n  );\n\n  // We're a stateless server, so disallow these\n  const handleSessionRequest = async (\n    _req: express.Request,\n    res: express.Response,\n  ) => {\n    res.writeHead(405).end(\n      JSON.stringify({\n        jsonrpc: '2.0',\n        error: {\n          code: -32000,\n          message: 'Method not allowed.',\n        },\n        id: null,\n      }),\n    );\n  };\n\n  app.get('/mcp', handleSessionRequest);\n  app.delete('/mcp', handleSessionRequest);\n\n  // SSE for older clients\n  const transports = {\n    sse: {} as Record<string, SSEServerTransport>,\n  };\n\n  app.get(\n    '/sse',\n    requireTokenMiddleware('sse'),\n    async (req: Request, res: Response) => {\n      const server = createMCPServer();\n      const transport = new SSEServerTransport('/messages', res);\n      res.on('close', () => {\n        delete transports.sse[transport.sessionId];\n      });\n\n      try {\n        const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n        wrapServerWithTracing(server, tracer, {\n          'client.client_id': tokens.mcpToken.client?.client_id,\n          'client.name': tokens.mcpToken.client?.client_name,\n          'client.id': tokens.mcpToken.client?.id,\n          'client.scope': tokens.mcpToken.client?.scope,\n          'client.uri': tokens.mcpToken.client?.client_uri,\n          'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n        });\n\n        registerTools(server);\n        transports.sse[transport.sessionId] = transport;\n      } catch (e) {\n        console.error('Error handling MCP SSE request:', e);\n        if (!res.headersSent) {\n          res.status(500).json({\n            jsonrpc: '2.0',\n            error: {\n              code: -32603,\n              message: 'Internal server error',\n            },\n            id: null,\n          });\n        }\n        return;\n      }\n\n      await server.connect(transport);\n    },\n  );\n\n  // Legacy message endpoint for older clients\n  app.post('/messages', async (req, res) => {\n    const sessionId = req.query.sessionId as string;\n    const transport = transports.sse[sessionId];\n    if (transport) {\n      await transport.handlePostMessage(req, res, req.body);\n    } else {\n      res.status(400).send('No transport found for sessionId');\n    }\n  });\n\n  app.get('/', (_req, res: Response) => {\n    res\n      .status(200)\n      .set('Content-Type', 'text/html; charset=UTF-8')\n      .send(indexHtml(oauthConfig.serverOrigin));\n  });\n\n  app.get('/health', (_req, res: Response) => {\n    res.status(200).send('Tip top!');\n  });\n\n  const port = parseInt(process.env.PORT || '3123');\n  const host = process.env.IN_FLY ? '0.0.0.0' : 'localhost';\n\n  if (process.env.IN_FLY) {\n    app.set('trust proxy', 2);\n  }\n\n  app.listen(port, host, () => console.log(`listening on port ${port}`));\n}\n\nasync function main() {\n  if (process.env.SERVER_TYPE === 'http') {\n    return startSse();\n  }\n  return startStdio();\n}\n\nmain().catch((error) => {\n  console.error('Fatal error in main():', error);\n  process.exit(1);\n});\n"]}
Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��ݕ䞲Ȩ����-

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��ݕ䞲Ȩ����-

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��ݕ䞲Ȩ����-

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: {!jx �^�ӢG�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��\�)bz{E������

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: r����^��'��m��-��%�jzW(�ױ��趇(�������w

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��\�)bz{E������

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: {!jx �^�ӢG�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: {!jxE��z�S�G�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: r���V�~������쵪�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��^��'��m��-��%��d�ǫ���j�a��bz{l

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��^��'��m��-��%��d��Z��j�a

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: {!jx �^�ӢG�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��\�)bz{E������

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: r����^��'��m��-��%�jzW(�ױ��趇(�������w

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��\�)bz{E������

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: {!jx �^�ӢG�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: {!jxE��z�S�G�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: r���h?��'��ݮ��

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: r���V�~������쵪�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: "{-j{@vh� �Zm�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: J�b�'���ӭ�즊�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: J�b�'���ӭ�즊�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��ݕ䞲Ȩ����-

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��ݕ䞲Ȩ����-

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��ݕ䞲Ȩ����-

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: ��^��'��m��-��%��d

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: J�b�'���ӭ�즊�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
highDO-BASunknownMedium ConfidenceLine 0

Decoded base64 content: J�b�'���ӭ�즊�

Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (4.8 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (4.6 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumOB-001ObfuscationMedium ConfidenceLine 0

Possible Base64-encoded payload (long encoded string)

Detected by automated pattern matching (rule OB-001) with medium confidence. May be a false positive.

    78:           <p>
    79:             <a
>>> 80:               href="https://github.com/instantdb/instant/tree/main/client/packages/mcp"
    81:               >View the code on GitHub.</a
    82:             >
Report false positive
mediumOB-001ObfuscationMedium ConfidenceLine 0

Possible Base64-encoded payload (long encoded string)

Detected by automated pattern matching (rule OB-001) with medium confidence. May be a false positive.

>>> 1: {"version":3,"file":"index.html.js","sourceRoot":"","sources":["../src/index.html.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,CAAC,YAAoB,EAAU,EAAE;IAC5C,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,GAAG,YAAY,MAAM,CAAC;IACrC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAC9B,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAC/B,OAAO,CACR,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErB,MAAM,SAAS,GAAG,mDAAmD,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,YAAY,EAAE,CAAC;IAClH,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAoDG,SAAS;;;;;;;;;;wCAUQ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAwClC,CAAC;AACb,CAAC,CAAC;AAEF,eAAe,IAAI,CAAC","sourcesContent":["const html = (serverOrigin: string): string => {\n  const dev = !serverOrigin.startsWith('https');\n  const mcpUrl = `${serverOrigin}/mcp`;\n  const cursorConfig = Buffer.from(\n    JSON.stringify({ url: mcpUrl }),\n    'utf-8',\n  ).toString('base64');\n\n  const cursorUrl = `https://cursor.com/en/install-mcp?name=InstantDB${dev ? '%20Dev' : ''}&config=${cursorConfig}`;\n  return /* HTML */ `<!doctype html>\n    <html lang=\"en\">\n      <head>\n        <meta charset=\"UTF-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n        <title>InstantDB Remote MCP Server</title>\n        <style>\n          body {\n            font-family: sans-serif;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            margin: 64px;\n            color: #1c1e21;\n          }\n          .container {\n            text-align: center;\n            padding: 2rem;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n          }\n          .copy-container {\n            display: flex;\n            margin: 1rem;\n            width: 384px;\n          }\n          #mcpUrl {\n            flex-grow: 1; /* Allows input to fill available space */\n            padding: 0.5rem;\n            font-size: 1rem;\n            border: 1px solid #ccc;\n            border-right: none;\n            border-radius: 4px 0 0 4px;\n            background-color: #f9f9f9;\n          }\n          #copyButton {\n            padding: 0.5rem 1rem;\n            border: 1px solid #007bff;\n            background-color: #007bff;\n            color: white;\n            cursor: pointer;\n            border-radius: 0 4px 4px 0;\n            font-size: 1rem;\n          }\n        </style>\n      </head>\n      <body>\n        <div class=\"container\">\n          <h1>Welcome to InstantDB's remote MCP Server!</h1>\n\n          <p>\n            <a href=\"${cursorUrl}\">\n              <img\n                src=\"https://cursor.com/deeplink/mcp-install-dark.svg\"\n                alt=\"Add InstantDB's MCP server to Cursor\"\n                height=\"32\"\n              />\n            </a>\n          </p>\n\n          <div class=\"copy-container\">\n            <input type=\"text\" value=\"${mcpUrl}\" id=\"mcpUrl\" readonly />\n            <button id=\"copyButton\">Copy</button>\n          </div>\n\n          <p>\n            <a href=\"https://www.instantdb.com/docs/using-llms\"\n              >Learn more in the docs.</a\n            >\n          </p>\n\n          <p>\n            <a\n              href=\"https://github.com/instantdb/instant/tree/main/client/packages/mcp\"\n              >View the code on GitHub.</a\n            >\n          </p>\n        </div>\n\n        <script>\n          const copyButton = document.getElementById('copyButton');\n          const mcpUrlInput = document.getElementById('mcpUrl');\n\n          copyButton.addEventListener('click', () => {\n            // Use the modern Navigator Clipboard API\n            navigator.clipboard\n              .writeText(mcpUrlInput.value)\n              .then(() => {\n                // Provide visual feedback to the user\n                copyButton.textContent = 'Copied!';\n                // Reset the button text after 2 seconds\n                setTimeout(() => {\n                  copyButton.textContent = 'Copy';\n                }, 2000);\n              })\n              .catch((err) => {\n                console.error('Failed to copy text: ', err);\n              });\n          });\n        </script>\n      </body>\n    </html>`;\n};\n\nexport default html;\n"]}
Report false positive
mediumOB-001ObfuscationMedium ConfidenceLine 0

Possible Base64-encoded payload (long encoded string)

Detected by automated pattern matching (rule OB-001) with medium confidence. May be a false positive.

    15: import { init } from '@instantdb/admin';
    16: import schema from "./db/instant.schema.js";
>>> 17: import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
    18: import { addOAuthRoutes, ServiceProvider, tokensOfBearerToken, } from "./oauth-service-provider.js";
    19: import indexHtml from "./index.html.js";
Report false positive
mediumOB-001ObfuscationMedium ConfidenceLine 0

Possible Base64-encoded payload (long encoded string)

Detected by automated pattern matching (rule OB-001) with medium confidence. May be a false positive.

    3:   "version": "0.22.142",
    4:   "description": "Model Context Protocol (MCP) server for managing Instant apps, schemas, and permissions!",
>>> 5:   "homepage": "https://github.com/instantdb/instant/tree/main/client/packages/mcp",
    6:   "repository": {
    7:     "type": "git",
Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (5.2 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (5.2 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (5.1 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (5.2 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (5.2 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (5.1 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (4.7 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (4.5 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (4.7 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumOB-001ObfuscationMedium ConfidenceLine 0

Possible Base64-encoded payload (long encoded string)

Detected by automated pattern matching (rule OB-001) with medium confidence. May be a false positive.

>>> 1: {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport 'dotenv/config';\nimport express, { Request, Response } from 'express';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { parseArgs } from 'node:util';\nimport version from './version.ts';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { HoneycombSDK } from '@honeycombio/opentelemetry-node';\nimport {\n  trace,\n  SpanKind,\n  SpanStatusCode,\n  Tracer,\n  Attributes,\n} from '@opentelemetry/api';\n\nimport {\n  createOAuthMetadata,\n  mcpAuthRouter,\n} from '@modelcontextprotocol/sdk/server/auth/router.js';\nimport { pinoHttp } from 'pino-http';\nimport { pino } from 'pino';\nimport { init } from '@instantdb/admin';\n\nimport schema from './db/instant.schema.ts';\nimport { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';\nimport {\n  addOAuthRoutes,\n  OAuthConfig,\n  ServiceProvider,\n  tokensOfBearerToken,\n} from './oauth-service-provider.ts';\nimport { KeyConfig } from './crypto.ts';\nimport indexHtml from './index.html.ts';\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\n\n// Helpers\n// -----------\nfunction createMCPServer(): McpServer {\n  return new McpServer({\n    name: '@instantdb/mcp',\n    version,\n  });\n}\n\n// Tool Registration\n// -----------\n\n// Adds tracing to server.tool\nfunction wrapServerWithTracing(\n  server: McpServer,\n  tracer: Tracer,\n  attrs: Attributes,\n): McpServer {\n  const originalTool = server.tool.bind(server);\n\n  server.tool = function (name: string, ...args: any[]): any {\n    // Find the callback (it's always the last argument)\n    const callback = args[args.length - 1];\n    const otherArgs = args.slice(0, -1);\n\n    // Wrap the callback with tracing\n    const wrappedCallback = async (...callbackArgs: any[]) => {\n      const span = tracer.startSpan(`tool.${name}`, {\n        attributes: attrs,\n      });\n      try {\n        const result = await callback(...callbackArgs);\n        span.setStatus({ code: SpanStatusCode.OK });\n        return result;\n      } catch (error) {\n        span.setStatus({ code: SpanStatusCode.ERROR });\n        span.recordException(error as Error);\n        throw error;\n      } finally {\n        span.end();\n      }\n    };\n\n    return originalTool(\n      name,\n      // @ts-expect-error: not sure how to type this\n      ...otherArgs,\n      wrappedCallback,\n    );\n  } as any;\n\n  return server;\n}\n\nfunction registerTools(server: McpServer) {\n  server.tool(\n    'learn',\n    \"If you don't have any context provided about InstantDB, use this tool to learn about it!\",\n    {},\n    async () => {\n      const instructions = `\n      You can learn about InstantDB by fetching our rules file for agents:\n\n      https://www.instantdb.com/llm-rules/AGENTS.md\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'get-schema',\n    'Fetch schema for an app by its ID!',\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      You can fetch the schema for the app by using the instant-cli tool:\n\n      \\`\\`\\`\n      npx instant-cli pull schema --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts. Now 'instant.schema.ts' with contain the schema for the app.\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'get-perms',\n    'Fetch permissions for an app by its ID',\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      You fetch the permissions for the app by using the instant-cli tool:\n\n      \\`\\`\\`\n      npx instant-cli pull perms --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts. Now 'instant.perms.ts' will contain the permissions for the app.\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'push-schema',\n    `Push local schema changes for an app to the server. Do this after updating your local 'instant.schema.ts' file.\n    If you don't have an instant.schema.ts file yet, use the get-schema tool to learn how to get this file.`,\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      Push schema changes by using the instant-cli tool:\n\n\n      \\`\\`\\`\n      npx instant-cli push schema --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts.\n\n      By default the instant-cli tool will assume new fields from the previous schema are additions and missing fields are deletions.\n      If you want to rename fields as part of your schema changes you can use the --rename flag to specify renames.\n\n      \\`\\`\\`\n      npx instant-cli push schema --app ${appId} --token ${adminToken} --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes\n      \\`\\`\\`\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'push-perms',\n    `Push local permissions changes for an app to the server. Do this after updating your local instant.perms.ts file.\n    If you don't have an instant.perms.ts file yet, use the get-perms tool to learn how to get this file.`,\n    {\n      appId: z.string().uuid().describe('UUID of the app'),\n      adminToken: z\n        .string()\n        .uuid()\n        .describe('UUID of the admin token for the app'),\n    },\n    async ({ appId, adminToken }) => {\n      const instructions = `\n      Push permission changes by using the instant-cli tool:\n\n      \\`\\`\\`\n      npx instant-cli push schema --app ${appId} --token ${adminToken} --yes\n      \\`\\`\\`\n\n      We supply the --yes flag to skip confirmation prompts.\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'query',\n    'Execute a query againt an app. Useful for inspecting data in the app.',\n    {},\n    async () => {\n      const instructions = `\n      You can query data for an app by writing and executing a script using the\n      Admin SDK. Here's an example script for fetching a habit and its completions:\n\n      \\`\\`\\`typescript\n      import { init } from \"@instantdb/admin\";\n      import \"dotenv/config\";\n\n      const adminDb = init({\n        appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,\n        adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,\n      });\n\n      async function fetchHabit(habitName: string) {\n        const { habits } = await adminDb.query({\n          habits: {\n            $: { where: { name: habitName } },\n            completions: {},\n          },\n        });\n        console.log(habits);\n      }\n\n      fetchHabit(\"Read\");\n      \\`\\`\\`\n\n      If you're unsure how to write queries, refer to the documentation:\n\n      https://instantdb.com/docs/instaql.md\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n\n  server.tool(\n    'transact',\n    'Execute a transaction against an app. Useful for seeding or modifying data in the app.',\n    {},\n    async () => {\n      const instructions = `\n      You can transact data for an app by writing and executing a script using the\n      Admin SDK. Here's an example script for seeding a microblog app with some posts:\n\n      \\`\\`\\`typescript\n      import { init, id } from \"@instantdb/admin\";\n      import \"dotenv/config\";\n\n      const adminDb = init({\n        appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,\n        adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,\n      });\n\n      interface Post {\n        id: number;\n        author: string;\n        handle: string;\n        color: string;\n        content: string;\n        timestamp: string;\n        likes: number;\n        liked: boolean;\n      }\n\n      const mockPosts: Post[] = [\n        {\n          author: 'Sarah Chen',\n          handle: 'sarahchen',\n          color: 'bg-blue-100',\n          content: 'Just launched my new project! Really excited to share it with everyone.',\n          timestamp: '2h ago',\n          likes: 12,\n          liked: false,\n        },\n        {\n          author: 'Alex Rivera',\n          handle: 'alexrivera',\n          color: 'bg-purple-100',\n          content: 'Beautiful sunset today. Nature never stops amazing me.',\n          timestamp: '4h ago',\n          likes: 19,\n          liked: true,\n        },\n        {\n          author: 'Jordan Lee',\n          handle: 'jordanlee',\n          color: 'bg-pink-100',\n          content: 'Working on something cool with Next.js and TypeScript. Updates coming soon!',\n          timestamp: '6h ago',\n          likes: 7,\n          liked: false,\n        },\n      ];\n\n      function friendlyTimeToTimestamp(friendlyTime: string) {\n        const hours = parseInt(friendlyTime);\n        const now = Date.now();\n        return now - (hours * 60 * 60 * 1000);\n      }\n\n      function seed() {\n        console.log(\"Seeding db...\");\n        mockPosts.forEach(post => {\n          const userId = id();\n          const postId = id();\n          const user = adminDb.tx.$users[userId].create({});\n          const profile = adminDb.tx.profiles[userId].create({\n            displayName: post.author,\n            handle: post.handle,\n          }).link({ user: userId });\n          const postEntity = adminDb.tx.posts[postId].create({\n            color: post.color,\n            content: post.content,\n            timestamp: friendlyTimeToTimestamp(post.timestamp),\n          }).link({ author: userId });\n          const likes = Array.from({ length: post.likes }, () => adminDb.tx.likes[id()].create({ postId, userId }).link({ post: postId, user: userId }));\n          adminDb.transact([user, profile, postEntity, ...likes]);\n        })\n      }\n\n      seed();\n      \\`\\`\\`\n\n      If you're unsure how to make transactions, refer to the documentation:\n\n      https://instantdb.com/docs/instaml.md\n      `;\n\n      return {\n        content: [\n          {\n            type: 'text',\n            text: instructions,\n          },\n        ],\n      };\n    },\n  );\n}\n\nasync function startStdio() {\n  const {\n    values: { token, ['api-url']: apiUrl },\n  } = parseArgs({\n    options: {\n      token: {\n        type: 'string',\n      },\n      ['api-url']: {\n        type: 'string',\n      },\n    },\n  });\n\n  const accessToken = token || process.env.INSTANT_ACCESS_TOKEN;\n  if (!accessToken) {\n    console.error(\n      'Provide an access token using --token or set INSTANT_ACCESS_TOKEN environment variable',\n    );\n    process.exit(1);\n  }\n\n  const server = createMCPServer();\n  registerTools(server);\n\n  const transport = new StdioServerTransport();\n  await server.connect(transport);\n  console.error('Instant Platform MCP Server running on stdio');\n}\n\nfunction ensureEnv(key: string): string {\n  const v = process.env[key];\n  if (!v) {\n    throw new Error(`Missing environment variable ${key}`);\n  }\n  return v;\n}\n\nasync function startSse() {\n  const honeycomb = new HoneycombSDK({\n    apiKey: process.env.HONEYCOMB_API_KEY,\n    serviceName: 'mcp-server',\n  });\n\n  if (process.env.HONEYCOMB_API_KEY) {\n    honeycomb.start();\n  }\n\n  const tracer = trace.getTracer('mcp-server');\n\n  const db = init({\n    adminToken: ensureEnv('INSTANT_ADMIN_TOKEN'),\n    appId: ensureEnv('INSTANT_APP_ID'),\n    schema,\n    disableValidation: true,\n  });\n\n  const oauthConfig: OAuthConfig = {\n    clientId: ensureEnv('INSTANT_OAUTH_CLIENT_ID'),\n    clientSecret: ensureEnv('INSTANT_OAUTH_CLIENT_SECRET'),\n    serverOrigin: ensureEnv('SERVER_ORIGIN'),\n  };\n\n  const keyConfig: KeyConfig = JSON.parse(ensureEnv('INSTANT_AES_KEY'));\n\n  const app = express();\n  const logger = pino({ level: 'info' });\n\n  app.use((req, res, next) => {\n    const span = tracer.startSpan('http-req', {\n      kind: SpanKind.SERVER,\n      attributes: {\n        'http.method': req.method,\n        'http.url': req.url,\n        'http.target': req.path,\n        'http.host': req.get('host'),\n        'http.scheme': req.protocol,\n      },\n    });\n\n    const originalEnd = res.end.bind(res);\n    res.end = function (this: typeof res, ...args: any[]): typeof res {\n      span.setAttribute('http.status_code', res.statusCode);\n      span.setStatus({\n        code: res.statusCode >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK,\n      });\n      span.end();\n      return originalEnd(...args);\n    };\n\n    next();\n  });\n\n  app.use(\n    pinoHttp({\n      logger,\n      autoLogging: {\n        ignore(req) {\n          return req.url === '/health';\n        },\n      },\n    }),\n  );\n  app.use(express.json());\n\n  const proxyProvider = new ServiceProvider(db, oauthConfig, keyConfig);\n\n  const authRouterOptions = {\n    scopesSupported: ['apps-read', 'apps-write'],\n    provider: proxyProvider,\n    issuerUrl: new URL(oauthConfig.serverOrigin),\n    baseUrl: new URL(oauthConfig.serverOrigin),\n    serviceDocumentationUrl: new URL('https://instantdb.com/docs'),\n  };\n\n  const oauthMetadata = createOAuthMetadata(authRouterOptions);\n\n  app.use(mcpAuthRouter(authRouterOptions));\n\n  addOAuthRoutes(app, db, oauthConfig);\n\n  app.get('/.well-known/oauth-protected-resource/mcp', (_req, res) => {\n    res.json({\n      resource: `${oauthConfig.serverOrigin}/mcp`,\n      authorization_servers: [oauthMetadata.issuer],\n      scopes_supported: oauthMetadata.scopes_supported,\n      resource_documentation: 'https://instantdb.com/docs',\n    });\n  });\n\n  app.get('/.well-known/oauth-protected-resource/sse', (_req, res) => {\n    res.json({\n      resource: `${oauthConfig.serverOrigin}/mcp`,\n      authorization_servers: [oauthMetadata.issuer],\n      scopes_supported: oauthMetadata.scopes_supported,\n      resource_documentation: 'https://instantdb.com/docs',\n    });\n  });\n\n  const requireTokenMiddleware = (path: string) =>\n    requireBearerAuth({\n      verifier: proxyProvider,\n      resourceMetadataUrl: `${oauthConfig.serverOrigin}/.well-known/oauth-protected-resource/${path}`,\n    });\n\n  // Handle POST requests for client-to-server communication\n  app.post(\n    '/mcp',\n    requireTokenMiddleware('mcp'),\n    async (req: Request, res: Response) => {\n      const server = createMCPServer();\n      try {\n        const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n        wrapServerWithTracing(server, tracer, {\n          'client.client_id': tokens.mcpToken.client?.client_id,\n          'client.name': tokens.mcpToken.client?.client_name,\n          'client.id': tokens.mcpToken.client?.id,\n          'client.scope': tokens.mcpToken.client?.scope,\n          'client.uri': tokens.mcpToken.client?.client_uri,\n          'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n        });\n        registerTools(server);\n        const transport: StreamableHTTPServerTransport =\n          new StreamableHTTPServerTransport({\n            sessionIdGenerator: undefined,\n          });\n\n        req.on('close', () => {\n          transport.close();\n          server.close();\n        });\n        await server.connect(transport);\n        await transport.handleRequest(req, res, req.body);\n      } catch (e) {\n        console.error('Error handling MCP request:', e);\n        if (!res.headersSent) {\n          res.status(500).json({\n            jsonrpc: '2.0',\n            error: {\n              code: -32603,\n              message: 'Internal server error',\n            },\n            id: null,\n          });\n        }\n      }\n    },\n  );\n\n  // We're a stateless server, so disallow these\n  const handleSessionRequest = async (\n    _req: express.Request,\n    res: express.Response,\n  ) => {\n    res.writeHead(405).end(\n      JSON.stringify({\n        jsonrpc: '2.0',\n        error: {\n          code: -32000,\n          message: 'Method not allowed.',\n        },\n        id: null,\n      }),\n    );\n  };\n\n  app.get('/mcp', handleSessionRequest);\n  app.delete('/mcp', handleSessionRequest);\n\n  // SSE for older clients\n  const transports = {\n    sse: {} as Record<string, SSEServerTransport>,\n  };\n\n  app.get(\n    '/sse',\n    requireTokenMiddleware('sse'),\n    async (req: Request, res: Response) => {\n      const server = createMCPServer();\n      const transport = new SSEServerTransport('/messages', res);\n      res.on('close', () => {\n        delete transports.sse[transport.sessionId];\n      });\n\n      try {\n        const tokens = await tokensOfBearerToken(db, req.auth!.token);\n\n        wrapServerWithTracing(server, tracer, {\n          'client.client_id': tokens.mcpToken.client?.client_id,\n          'client.name': tokens.mcpToken.client?.client_name,\n          'client.id': tokens.mcpToken.client?.id,\n          'client.scope': tokens.mcpToken.client?.scope,\n          'client.uri': tokens.mcpToken.client?.client_uri,\n          'client.redirect_urls': tokens.mcpToken.client?.redirect_uris,\n        });\n\n        registerTools(server);\n        transports.sse[transport.sessionId] = transport;\n      } catch (e) {\n        console.error('Error handling MCP SSE request:', e);\n        if (!res.headersSent) {\n          res.status(500).json({\n            jsonrpc: '2.0',\n            error: {\n              code: -32603,\n              message: 'Internal server error',\n            },\n            id: null,\n          });\n        }\n        return;\n      }\n\n      await server.connect(transport);\n    },\n  );\n\n  // Legacy message endpoint for older clients\n  app.post('/messages', async (req, res) => {\n    const sessionId = req.query.sessionId as string;\n    const transport = transports.sse[sessionId];\n    if (transport) {\n      await transport.handlePostMessage(req, res, req.body);\n    } else {\n      res.status(400).send('No transport found for sessionId');\n    }\n  });\n\n  app.get('/', (_req, res: Response) => {\n    res\n      .status(200)\n      .set('Content-Type', 'text/html; charset=UTF-8')\n      .send(indexHtml(oauthConfig.serverOrigin));\n  });\n\n  app.get('/health', (_req, res: Response) => {\n    res.status(200).send('Tip top!');\n  });\n\n  const port = parseInt(process.env.PORT || '3123');\n  const host = process.env.IN_FLY ? '0.0.0.0' : 'localhost';\n\n  if (process.env.IN_FLY) {\n    app.set('trust proxy', 2);\n  }\n\n  app.listen(port, host, () => console.log(`listening on port ${port}`));\n}\n\nasync function main() {\n  if (process.env.SERVER_TYPE === 'http') {\n    return startSse();\n  }\n  return startStdio();\n}\n\nmain().catch((error) => {\n  console.error('Fatal error in main():', error);\n  process.exit(1);\n});\n"]}
Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (4.7 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive
mediumOB-001ObfuscationMedium ConfidenceLine 0

Possible Base64-encoded payload (long encoded string)

Detected by automated pattern matching (rule OB-001) with medium confidence. May be a false positive.

    53: function patchClientForScopes(client) {
    54:     if (!client.scope ||
>>> 55:         // https://github.com/modelcontextprotocol/modelcontextprotocol/issues/653
    56:         // Anthropic says it's fixed, but it doesn't seem like it
    57:         client.scope?.includes('claudeai') ||
Report false positive
mediumOB-001ObfuscationMedium ConfidenceLine 0

Possible Base64-encoded payload (long encoded string)

Detected by automated pattern matching (rule OB-001) with medium confidence. May be a false positive.

>>> 1: {"version":3,"file":"oauth-service-provider.js","sourceRoot":"","sources":["../src/oauth-service-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n  Express,\n  NextFunction,\n  Request,\n  RequestHandler,\n  Response,\n  urlencoded,\n} from 'express';\nimport crypto from 'crypto';\nimport {\n  id,\n  InstantAdminDatabase,\n  InstaQLEntity,\n  InstaQLResult,\n  lookup,\n} from '@instantdb/admin';\nimport { AppSchema } from './db/instant.schema.ts';\nimport {\n  AuthorizationParams,\n  OAuthServerProvider,\n} from '@modelcontextprotocol/sdk/server/auth/provider.js';\nimport { OAuthRegisteredClientsStore } from '@modelcontextprotocol/sdk/server/auth/clients.js';\nimport {\n  OAuthClientInformationFull,\n  OAuthTokenRevocationRequest,\n  OAuthTokens,\n} from '@modelcontextprotocol/sdk/shared/auth.js';\nimport { decrypt, encrypt, hash, KeyConfig } from './crypto.ts';\nimport { exchangeCodeForToken } from '@instantdb/platform';\nimport { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';\nimport { PlatformApiAuth } from '../../platform/dist/esm/api.js';\nimport { PlatformApi } from '@instantdb/platform';\nimport cookieParser from 'cookie-parser';\nimport {\n  InvalidRequestError,\n  InvalidTokenError,\n} from '@modelcontextprotocol/sdk/server/auth/errors.js';\n\nexport type OAuthConfig = {\n  clientId: string;\n  clientSecret: string;\n  serverOrigin: string;\n};\n\nexport async function tokensOfBearerToken(\n  db: InstantAdminDatabase<AppSchema>,\n  token: string,\n): Promise<{\n  mcpToken: InstaQLResult<\n    AppSchema,\n    { mcpTokens: { client: {}; instantToken: {} } }\n  >['mcpTokens'][number];\n  instantToken: InstaQLEntity<AppSchema, 'instantTokens'>;\n}> {\n  const queryRes = await db.query({\n    mcpTokens: {\n      $: {\n        where: {\n          tokenHash: hash(token),\n        },\n      },\n      client: {},\n      instantToken: {},\n    },\n  });\n\n  const tokenEnt = queryRes.mcpTokens[0];\n  if (!tokenEnt) {\n    throw new InvalidTokenError('Token not found.');\n  }\n\n  return { mcpToken: tokenEnt, instantToken: tokenEnt.instantToken! };\n}\n\nexport function makeApiAuth(\n  oauthConfig: OAuthConfig,\n  key: KeyConfig,\n  db: InstantAdminDatabase<AppSchema>,\n  instantTokenEnt: InstaQLEntity<AppSchema, 'instantTokens'>,\n): PlatformApiAuth {\n  return {\n    accessToken: decrypt({\n      key,\n      enc: instantTokenEnt.accessToken,\n      aad: instantTokenEnt.id,\n    }),\n    refreshToken: decrypt({\n      key,\n      enc: instantTokenEnt.refreshToken,\n      aad: instantTokenEnt.id,\n    }),\n    clientId: oauthConfig.clientId,\n    clientSecret: oauthConfig.clientSecret,\n    onRefresh: async ({ accessToken, expiresAt }) => {\n      await db.transact(\n        db.tx.instantTokens[instantTokenEnt.id].update({\n          accessToken: encrypt({\n            key,\n            aad: instantTokenEnt.id,\n            plaintext: accessToken,\n          }),\n          expiresAt: expiresAt.getTime(),\n        }),\n      );\n    },\n  };\n}\n\nfunction patchClientForScopes(\n  client: OAuthClientInformationFull,\n): OAuthClientInformationFull {\n  if (\n    !client.scope ||\n    // https://github.com/modelcontextprotocol/modelcontextprotocol/issues/653\n    // Anthropic says it's fixed, but it doesn't seem like it\n    client.scope?.includes('claudeai') ||\n    // Fix for mcp-remote. Unclear why it can't find the scopes\n    // and falls back to its default\n    client.scope === 'openid email profile'\n  ) {\n    return { ...client, scope: 'apps-read apps-write' };\n  }\n  return client;\n}\n\nexport class ServiceProvider implements OAuthServerProvider {\n  #db: InstantAdminDatabase<AppSchema>;\n  #oauthConfig: OAuthConfig;\n  #keyConfig: KeyConfig;\n\n  constructor(\n    db: InstantAdminDatabase<AppSchema>,\n    oauthConfig: OAuthConfig,\n    keyConfig: KeyConfig,\n  ) {\n    this.#db = db;\n    this.#oauthConfig = oauthConfig;\n    this.#keyConfig = keyConfig;\n  }\n\n  get clientsStore(): OAuthRegisteredClientsStore {\n    return {\n      getClient: async (clientId: string) => {\n        const res = await this.#db.query({\n          clients: { $: { where: { client_id: clientId } } },\n        });\n        const client = res.clients[0];\n        if (!client) {\n          return undefined;\n        }\n\n        return {\n          ...client,\n          ...(client.client_secret\n            ? {\n                client_secret: decrypt({\n                  key: this.#keyConfig,\n                  enc: client.client_secret,\n                  aad: client.client_id,\n                }),\n              }\n            : {}),\n        } as OAuthClientInformationFull;\n      },\n\n      registerClient: async (rawClient: OAuthClientInformationFull) => {\n        const client = {\n          ...patchClientForScopes(rawClient),\n        };\n\n        await this.#db.transact(\n          this.#db.tx.clients[id()].update({\n            ...client,\n            ...(client.client_secret\n              ? {\n                  client_secret: encrypt({\n                    key: this.#keyConfig,\n                    aad: client.client_id,\n                    plaintext: client.client_secret,\n                  }),\n                }\n              : {}),\n          }),\n        );\n        return client;\n      },\n    };\n  }\n  async authorize(\n    client: OAuthClientInformationFull,\n    params: AuthorizationParams,\n    res: Response,\n  ): Promise<void> {\n    // Tag the cookie with a prefix in case multiple have the same key\n    const cookie = `_imcp_${crypto.randomUUID()}`;\n    const cookieHash = hash(cookie);\n    const state = crypto.randomUUID();\n\n    await this.#db.transact(\n      this.#db.tx.redirects[id()]\n        .update({\n          cookieHash,\n          authParams: params,\n          state,\n          clientToken: crypto.randomUUID(),\n          expiresAt: new Date(Date.now() + 1000 * 60 * 10).getTime(),\n        })\n        .link({ client: lookup('client_id', client.client_id) }),\n    );\n    res\n      .cookie('__session', cookie, {\n        httpOnly: true,\n        secure: this.#oauthConfig.serverOrigin.startsWith('https'),\n        sameSite: 'lax',\n        path: '/oauth',\n        expires: new Date(Date.now() + 1000 * 60 * 5),\n      })\n      .redirect('/oauth/start');\n  }\n\n  async challengeForAuthorizationCode(\n    _client: OAuthClientInformationFull,\n    authorizationCode: string,\n  ): Promise<string> {\n    const mcpCodeHash = hash(authorizationCode);\n\n    const queryRes = await this.#db.query({\n      redirects: { $: { where: { mcpCodeHash } } },\n    });\n\n    const redirect = queryRes.redirects[0];\n\n    if (!redirect) {\n      throw new Error('Could not find OAuth request.');\n    }\n\n    if (!redirect.exchangedForInstantCode) {\n      throw new Error(\n        'OAuth flow is in an invalid state. Expected to exchange a code for a token first.',\n      );\n    }\n\n    return redirect.authParams.codeChallenge;\n  }\n\n  async exchangeAuthorizationCode(\n    client: OAuthClientInformationFull,\n    authorizationCode: string,\n    // Already checked in `challengeForAuthorizationCode`\n    _codeVerifier?: string,\n    redirectUri?: string,\n  ): Promise<OAuthTokens> {\n    const mcpCodeHash = hash(authorizationCode);\n\n    const queryRes = await this.#db.query({\n      redirects: { $: { where: { mcpCodeHash } } },\n    });\n\n    const redirect = queryRes.redirects[0];\n\n    if (!redirect) {\n      throw new InvalidRequestError('Could not find OAuth request.');\n    }\n\n    await this.#db.transact(this.#db.tx.redirects[redirect.id].delete());\n\n    const originalRedirectUri = redirect.authParams.redirectUri;\n    if (originalRedirectUri !== redirectUri) {\n      throw new InvalidRequestError('Invalid redirect_uri.');\n    }\n\n    if (!redirect.exchangedForInstantCode || !redirect.instantCode) {\n      throw new InvalidRequestError(\n        'OAuth flow is in an invalid state. Expected to exchange a code for a token first.',\n      );\n    }\n\n    const code = redirect.instantCode;\n\n    const tokenInfo = await exchangeCodeForToken({\n      code,\n      clientId: this.#oauthConfig.clientId,\n      clientSecret: this.#oauthConfig.clientSecret,\n      redirectUri: `${this.#oauthConfig.serverOrigin}/oauth/external-redirect`,\n    });\n\n    const instantTokenExpiresAt = tokenInfo.expiresAt;\n    const mcpTokenExpiresAt = new Date(\n      instantTokenExpiresAt.getTime() - 1000 * 60 * 60,\n    );\n\n    const mcpToken = `at_${crypto.randomUUID()}`;\n    const mcpRefreshToken = `rt_${crypto.randomUUID()}`;\n    const mcpTokenId = id();\n    const mcpRefreshTokenId = id();\n    const instantTokenId = id();\n\n    await this.#db.transact([\n      this.#db.tx.instantTokens[instantTokenId]\n        .update({\n          accessToken: encrypt({\n            key: this.#keyConfig,\n            aad: instantTokenId,\n            plaintext: tokenInfo.accessToken,\n          }),\n          expiresAt: instantTokenExpiresAt.getTime(),\n          refreshToken: encrypt({\n            key: this.#keyConfig,\n            aad: instantTokenId,\n            plaintext: tokenInfo.refreshToken,\n          }),\n        })\n        .link({ client: lookup('client_id', client.client_id) }),\n      this.#db.tx.mcpTokens[mcpTokenId]\n        .update({\n          tokenHash: hash(mcpToken),\n          expiresAt: mcpTokenExpiresAt.getTime(),\n          scope: tokenInfo.scopes,\n        })\n        .link({ instantToken: instantTokenId })\n        .link({ mcpRefreshToken: mcpRefreshTokenId })\n        .link({ client: lookup('client_id', client.client_id) }),\n      this.#db.tx.mcpRefreshTokens[mcpRefreshTokenId]\n        .update({\n          tokenHash: hash(mcpRefreshToken),\n          scope: tokenInfo.scopes,\n        })\n        .link({ instantToken: instantTokenId })\n        .link({ client: lookup('client_id', client.client_id) }),\n    ]);\n\n    return {\n      access_token: mcpToken,\n      token_type: 'bearer',\n      expires_in: Math.floor((mcpTokenExpiresAt.getTime() - Date.now()) / 1000),\n      scope: tokenInfo.scopes,\n      refresh_token: mcpRefreshToken,\n    };\n  }\n\n  async exchangeRefreshToken(\n    client: OAuthClientInformationFull,\n    refreshToken: string,\n    _scopes?: string[],\n  ): Promise<OAuthTokens> {\n    const queryRes = await this.#db.query({\n      mcpRefreshTokens: {\n        $: {\n          where: {\n            tokenHash: hash(refreshToken),\n          },\n        },\n        client: {},\n        instantToken: {},\n      },\n    });\n\n    const tokenEnt = queryRes.mcpRefreshTokens[0];\n    if (!tokenEnt) {\n      throw new InvalidTokenError('Token not found.');\n    }\n\n    if (client.client_id !== tokenEnt.client!.client_id) {\n      throw new InvalidTokenError('Refresh token does not belong to client.');\n    }\n\n    const mcpToken = `at_${crypto.randomUUID()}`;\n    const expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24 * 14).getTime();\n    await this.#db.transact(\n      this.#db.tx.mcpTokens[id()]\n        .update({\n          tokenHash: hash(mcpToken),\n          expiresAt,\n          scope: tokenEnt.scope,\n        })\n        // instantToken is required, so we should be able to fix the types\n        // so we don't need the `!`s\n        .link({ instantToken: tokenEnt.instantToken!.id })\n        .link({ mcpRefreshToken: tokenEnt.id })\n        .link({ client: lookup('client_id', client.client_id) }),\n    );\n    return {\n      access_token: mcpToken,\n      token_type: 'bearer',\n      expires_in: Math.floor((Date.now() - expiresAt) / 1000),\n      refresh_token: refreshToken,\n      scope: tokenEnt.scope,\n    };\n  }\n\n  async verifyAccessToken(token: string): Promise<AuthInfo> {\n    const { instantToken, mcpToken } = await tokensOfBearerToken(\n      this.#db,\n      token,\n    );\n    const api = new PlatformApi({\n      auth: makeApiAuth(\n        this.#oauthConfig,\n        this.#keyConfig,\n        this.#db,\n        instantToken,\n      ),\n    });\n\n    try {\n      await api.tokenInfo();\n    } catch (e) {\n      throw new InvalidTokenError(\n        e instanceof Error ? e.message : 'Invalid token',\n      );\n    }\n\n    return {\n      clientId: mcpToken.client!.client_id,\n      scopes: mcpToken.scope.split(' '),\n      token,\n      expiresAt: new Date(mcpToken.expiresAt).getTime(),\n    };\n  }\n\n  async revokeToken(\n    _client: OAuthClientInformationFull,\n    request: OAuthTokenRevocationRequest,\n  ): Promise<void> {\n    const tokenHash = hash(request.token);\n\n    await this.#db.transact([\n      this.#db.tx.mcpTokens[lookup('tokenHash', tokenHash)].delete(),\n      this.#db.tx.mcpRefreshTokens[lookup('tokenHash', tokenHash)].delete(),\n    ]);\n  }\n}\n\ninterface ReqWithRedirect extends Request {\n  oauthRedirect?: InstaQLResult<\n    AppSchema,\n    {\n      redirects: {\n        client: {};\n      };\n    }\n  >['redirects'][number];\n}\n\nfunction useRedirectFromCookie(\n  db: InstantAdminDatabase<AppSchema>,\n): RequestHandler {\n  return async (req: ReqWithRedirect, res: Response, next: NextFunction) => {\n    const cookie = req.cookies.__session;\n    if (!cookie) {\n      res.status(400).send('Missing cookie, cannot complete OAuth flow.');\n      return;\n    }\n    const cookieHash = hash(cookie);\n\n    const queryRes = await db.query({\n      redirects: {\n        $: { where: { cookieHash } },\n        client: {},\n      },\n    });\n\n    const redirect = queryRes.redirects[0];\n\n    if (!redirect) {\n      res.status(400).send('Could not find OAuth flow, please try again.');\n      return;\n    }\n\n    if (new Date(redirect.expiresAt) < new Date()) {\n      await db.transact(db.tx.redirects[redirect.id].delete());\n      res.status(400).send('OAuth flow is expired, please try again.');\n      return;\n    }\n\n    req.oauthRedirect = redirect;\n    next();\n  };\n}\n\nasync function cleanupRedirect(\n  db: InstantAdminDatabase<AppSchema>,\n  redirect: NonNullable<ReqWithRedirect['oauthRedirect']>,\n) {\n  await db.transact(db.tx.redirects[redirect.id].delete());\n}\n\nfunction oauthStartHtml(\n  redirect: NonNullable<ReqWithRedirect['oauthRedirect']>,\n) {\n  const clientName = redirect.client?.client_name || 'Unknown client';\n  const redirectUri = encodeURI(redirect.authParams.redirectUri);\n\n  return /* HTML */ `<!DOCTYPE html>\n    <html lang=\"en\">\n      <head>\n        <meta charset=\"UTF-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n        <title>Authorize ${clientName}</title>\n        <style>\n          :root {\n            --primary-color: #007bff;\n            --primary-hover-color: #0056b3;\n            --secondary-color: #6c757d;\n            --secondary-hover-color: #5a6268;\n            --bg-color: #f8f9fa;\n            --card-bg-color: #ffffff;\n            --text-color: #212529;\n            --border-color: #dee2e6;\n            --uri-bg-color: #e9ecef;\n            --uri-border-color: #ced4da;\n            --border-radius: 8px;\n            --shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\n          }\n\n          body {\n            font-family: sans-serif;\n            background-color: var(--bg-color);\n            color: var(--text-color);\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            min-height: 100vh;\n            margin: 0;\n            padding: 1rem;\n            box-sizing: border-box;\n          }\n\n          .container {\n            background-color: var(--card-bg-color);\n            padding: 2.5rem;\n            border-radius: var(--border-radius);\n            box-shadow: var(--shadow);\n            max-width: 520px;\n            width: 100%;\n            /* CHANGED: Text is now left-aligned */\n            text-align: left;\n          }\n\n          h1 {\n            font-size: 1.75rem;\n            font-weight: 700;\n            margin-top: 0;\n            margin-bottom: 1rem;\n          }\n\n          p {\n            line-height: 1.6;\n            margin-bottom: 1rem; /* Adjusted margin for new layout */\n          }\n\n          .client-name {\n            font-weight: 700;\n            color: var(--primary-color);\n          }\n\n          /* NEW: Styling for the dedicated URL block */\n          .uri-display {\n            background-color: var(--uri-bg-color);\n            padding: 0.75rem 1rem;\n            margin-top: 0.5rem;\n            margin-bottom: 2rem;\n            border: 1px solid var(--uri-border-color);\n            border-radius: 6px;\n            font-family: 'Source Code Pro', monospace;\n            word-break: break-all;\n            font-size: 0.9rem;\n            color: var(--text-color);\n          }\n\n          .actions {\n            display: flex;\n            gap: 1rem;\n            justify-content: flex-start; /* Aligns buttons to the left */\n            margin-top: 2rem;\n          }\n\n          .actions form {\n            flex: 1 1 0;\n            display: flex;\n          }\n\n          .btn {\n            display: inline-block;\n            font-family: inherit;\n            font-size: 1rem;\n            font-weight: 500;\n            padding: 0.75rem 1rem;\n            border-radius: var(--border-radius);\n            border: 1px solid transparent;\n            cursor: pointer;\n            transition:\n              background-color 0.2s ease-in-out,\n              color 0.2s ease-in-out,\n              border-color 0.2s ease-in-out;\n            width: 100%;\n            text-decoration: none;\n            text-align: center;\n          }\n\n          .btn-primary {\n            background-color: var(--primary-color);\n            color: white;\n          }\n\n          .btn-primary:hover {\n            background-color: var(--primary-hover-color);\n          }\n\n          .btn-secondary {\n            background-color: transparent;\n            color: var(--secondary-color);\n            border-color: var(--border-color);\n          }\n\n          .btn-secondary:hover {\n            background-color: var(--secondary-color);\n            color: white;\n            border-color: var(--secondary-color);\n          }\n        </style>\n      </head>\n      <body>\n        <div class=\"container\">\n          <h1>Authorize Application</h1>\n          <p>\n            The application\n            <strong class=\"client-name\">${clientName}</strong> is requesting\n            permission to access your InstantDB account.\n          </p>\n\n          <p>\n            If you approve, you will first be sent to InstantDB to confirm, then\n            you will be redirected to the application at the following address:\n          </p>\n\n          <div class=\"uri-display\">${redirectUri}</div>\n\n          <div class=\"actions\">\n            <form method=\"POST\" action=\"/oauth/deny\">\n              <button type=\"submit\" class=\"btn btn-secondary\">Deny</button>\n            </form>\n            <form method=\"POST\" action=\"/oauth/redirect-from-start\">\n              <input\n                type=\"hidden\"\n                name=\"clientToken\"\n                value=\"${redirect.clientToken}\"\n              />\n              <button type=\"submit\" class=\"btn btn-primary\">Authorize</button>\n            </form>\n          </div>\n        </div>\n      </body>\n    </html>`;\n}\n\nasync function oauthStart(\n  db: InstantAdminDatabase<AppSchema>,\n  req: ReqWithRedirect,\n  res: Response,\n) {\n  const redirect = req.oauthRedirect!;\n  if (redirect.shownConfirmPage) {\n    await cleanupRedirect(db, redirect);\n    res\n      .status(400)\n      .send('OAuth request is in an invalid state. Please try again.');\n    return;\n  }\n  await db.transact(\n    db.tx.redirects[redirect.id].update({ shownConfirmPage: true }),\n  );\n\n  res\n    .status(200)\n    .set('Content-Type', 'text/html; charset=UTF-8')\n    .send(oauthStartHtml(redirect));\n}\n\nasync function oauthRedirectFromStart(\n  db: InstantAdminDatabase<AppSchema>,\n  oauthConfig: OAuthConfig,\n  req: ReqWithRedirect,\n  res: Response,\n) {\n  const redirect = req.oauthRedirect!;\n\n  if (!redirect.shownConfirmPage) {\n    await cleanupRedirect(db, redirect);\n    res\n      .status(400)\n      .send('OAuth request is in an invalid state. Please try again.');\n    return;\n  }\n\n  if (\n    !req.body.clientToken ||\n    !crypto.timingSafeEqual(\n      Buffer.from(req.body.clientToken, 'utf-8'),\n      Buffer.from(redirect.clientToken, 'utf-8'),\n    )\n  ) {\n    await cleanupRedirect(db, redirect);\n    res.status(400).send('Invalid OAuth request. Please try again.');\n    return;\n  }\n  const externalAuthUrl = new URL(\n    `https://api.instantdb.com/platform/oauth/start`,\n  );\n  externalAuthUrl.searchParams.set('client_id', oauthConfig.clientId);\n  externalAuthUrl.searchParams.set('response_type', 'code');\n  externalAuthUrl.searchParams.set('state', redirect.state);\n  externalAuthUrl.searchParams.set(\n    'scope',\n    redirect.authParams.scopes?.join(' ') ||\n      redirect.client!.scope ||\n      'apps-read apps-write',\n  );\n\n  externalAuthUrl.searchParams.set(\n    'redirect_uri',\n    `${oauthConfig.serverOrigin}/oauth/external-redirect`,\n  );\n\n  res.redirect(externalAuthUrl.toString());\n}\n\nasync function oauthExternalRedirect(\n  db: InstantAdminDatabase<AppSchema>,\n  req: ReqWithRedirect,\n  res: Response,\n) {\n  const redirect = req.oauthRedirect!;\n\n  if (redirect.exchangedForInstantCode) {\n    await cleanupRedirect(db, redirect);\n    res.status(400).send('OAuth flow is expired, please try again.');\n    return;\n  }\n\n  if (req.query.error) {\n    await cleanupRedirect(db, redirect);\n    const redirectUri = new URL(\n      (redirect.authParams as AuthorizationParams).redirectUri,\n    );\n    redirectUri.searchParams.set('error', req.query.error as string);\n    if (req.query.error_description) {\n      redirectUri.searchParams.set(\n        'error_description',\n        req.query.error_description as string,\n      );\n    }\n    res.redirect(redirectUri.toString());\n    return;\n  }\n\n  const instantCode = req.query.code as string | undefined;\n\n  if (!instantCode) {\n    await cleanupRedirect(db, redirect);\n    res\n      .status(400)\n      .send(\n        'Could not complete OAuth flow, missing code param. Please try again.',\n      );\n    return;\n  }\n\n  const state = req.query.state;\n\n  if (!state) {\n    await cleanupRedirect(db, redirect);\n    res\n      .status(400)\n      .send(\n        'Could not complete OAuth flow, missing state param. Please try again.',\n      );\n    return;\n  }\n\n  if (\n    !crypto.timingSafeEqual(\n      Buffer.from(state as string),\n      Buffer.from(redirect.state),\n    )\n  ) {\n    await cleanupRedirect(db, redirect);\n    res\n      .status(400)\n      .send(\n        'Could not complete OAuth flow, invalid state param. Please try again.',\n      );\n    return;\n  }\n\n  const mcpCode = crypto.randomUUID();\n  const mcpCodeHash = hash(mcpCode);\n\n  await db.transact(\n    db.tx.redirects[redirect.id].update({\n      instantCode,\n      mcpCodeHash,\n      exchangedForInstantCode: true,\n    }),\n  );\n\n  const mcpRedirectUri = new URL(redirect.authParams.redirectUri);\n\n  mcpRedirectUri.searchParams.set('code', mcpCode);\n  if (redirect.authParams.state) {\n    mcpRedirectUri.searchParams.set('state', redirect.authParams.state);\n  }\n\n  res.redirect(mcpRedirectUri.toString());\n}\n\nexport function addOAuthRoutes(\n  app: Express,\n  db: InstantAdminDatabase<AppSchema>,\n  oauthConfig: OAuthConfig,\n) {\n  app.get(\n    '/oauth/start',\n    cookieParser(),\n    useRedirectFromCookie(db),\n    async (req: Request, res: Response) => {\n      return await oauthStart(db, req, res);\n    },\n  );\n\n  app.post(\n    '/oauth/redirect-from-start',\n    cookieParser(),\n    useRedirectFromCookie(db),\n    urlencoded({ extended: true }),\n    async (req: Request, res: Response) => {\n      return await oauthRedirectFromStart(db, oauthConfig, req, res);\n    },\n  );\n\n  app.post(\n    '/oauth/deny',\n    cookieParser(),\n    useRedirectFromCookie(db),\n    async (req: ReqWithRedirect, res: Response) => {\n      const redirect = req.oauthRedirect!;\n      await db.transact(db.tx.redirects[redirect.id].delete());\n      const redirectUri = new URL(\n        (redirect.authParams as AuthorizationParams).redirectUri,\n      );\n      redirectUri.searchParams.set('error', 'access_denied');\n      res.redirect(redirectUri.toString());\n    },\n  );\n\n  app.get(\n    '/oauth/external-redirect',\n    cookieParser(),\n    useRedirectFromCookie(db),\n    async (req: Request, res: Response) => {\n      return await oauthExternalRedirect(db, req, res);\n    },\n  );\n}\n"]}
Report false positive
mediumEN-001unknownMedium ConfidenceLine 0

High-entropy string (4.7 bits/char) — possible encoded payload

Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.

Report false positive

Scan History

DateRiskFindings
Feb 23, 2026critical75
Feb 22, 2026critical75