onvibe.run

← All docs

Expose an MCP server from your app

Your app can be an MCP server: AI assistants (Claude as a connector, Claude Code, LM Studio…) connect to it and call tools you define, authenticated per end-user via OAuth. The platform handles the whole transport (JSON-RPC 2.0 over Streamable HTTP) and the OAuth — you just register tools.

One call: mountMcp

import { mountMcp, currentUser } from "./.onvibe/helpers.ts";

export default async function handler(req: Request): Promise<Response> {
  const mcp = await mountMcp(req, {
    auth: "oauth",                       // authenticate each MCP client per end-user
    tools: [
      {
        name: "list_notes",
        description: "List the signed-in user's notes",
        inputSchema: { type: "object", properties: {} },
        handler: async (_args, ctx) => await listNotes(ctx.user!.id),
      },
      {
        name: "create_note",
        description: "Create a note",
        inputSchema: {
          type: "object",
          properties: { text: { type: "string" } },
          required: ["text"],
        },
        handler: async (args, ctx) => await createNote(ctx.user!.id, String(args.text)),
      },
    ],
  });
  if (mcp) return mcp;   // it was an MCP request (/mcp) — handled

  // ...the rest of your app (normal web UI)
}

mountMcp returns a Response for MCP requests (path /mcp) and null otherwise, so it composes with your existing routes. It handles initialize, ping, tools/list, tools/call, notifications, batching, CORS and the session headers for you.

Each tool handler(args, ctx) receives the call arguments and ctx.user — the authenticated end-user { id, email } (or null if auth: "none"). Use ctx.user.id as the stable key for that person's data. Return a string, a JSON-serializable value, or an MCP content object; mountMcp wraps it.

Turning on OAuth (required for auth: "oauth")

MCP OAuth authenticates against your app's managed users, so the app must have user accounts:

set_access_policy({ project_id: "my-app", policy: "signup" })   // or "allowlist"

That's it. The platform then acts as the OAuth Authorization Server for your app:

The client's connection URL is https://<your-app-domain>/mcp (works on the .onvibe.run URL and on custom domains).

Notes

Read this page as Markdown (best for LLMs) · plain text
onvibe.run · home · all docs