core/apps/webapp/app/routes/api.v1.oauth.callback.mcp.tsx
Harshith Mullapudi ef320394d5 1. Feat: added ingestion floating status
2. OAuth for mcp
2025-07-15 22:02:41 +05:30

102 lines
3.0 KiB
TypeScript

import { type LoaderFunctionArgs } from "@remix-run/node";
import { getIntegrationDefinitionWithId } from "~/services/integrationDefinition.server";
import { runIntegrationTrigger } from "~/services/integration.server";
import { IntegrationEventType } from "@core/types";
import { createMCPAuthClient } from "@core/mcp-proxy";
import { logger } from "~/services/logger.service";
import { env } from "~/env.server";
import { getIntegrationDefinitionForState } from "~/services/oauth/oauth.server";
const CALLBACK_URL = `${env.APP_ORIGIN}/api/v1/oauth/callback`;
const MCP_CALLBACK_URL = `${CALLBACK_URL}/mcp`;
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const authorizationCode = url.searchParams.get("code");
const state = url.searchParams.get("state");
if (!authorizationCode || !state) {
return new Response(null, {
status: 302,
headers: {
Location: `${env.APP_ORIGIN}/integrations?success=false&error=${encodeURIComponent(
"Missing authorization code or state",
)}`,
},
});
}
const { integrationDefinitionId, redirectURL } =
await getIntegrationDefinitionForState(state);
try {
// For now, we'll assume Linear integration - in the future this should be derived from state
const integrationDefinition = await getIntegrationDefinitionWithId(
integrationDefinitionId,
);
if (!integrationDefinition) {
throw new Error("Integration definition not found");
}
const spec = integrationDefinition.spec as any;
if (!spec.mcpAuth) {
throw new Error("MCP auth configuration not found for this integration");
}
const { transportStrategy, serverUrl } = spec.mcpAuth;
const authClient = createMCPAuthClient({
serverUrl,
transportStrategy: transportStrategy || "sse-first",
redirectUrl: MCP_CALLBACK_URL,
});
const result = await authClient.completeOAuthFlow({
authorizationCode,
state,
scope: "read write",
});
// Run integration trigger with MCP OAuth response
await runIntegrationTrigger(
integrationDefinition,
{
event: IntegrationEventType.SETUP,
eventBody: {
oauthResponse: result,
oauthParams: {
code: authorizationCode,
state,
redirect_uri: MCP_CALLBACK_URL,
},
integrationDefinition,
},
},
// We need to get userId from somewhere - for now using undefined
undefined,
);
return new Response(null, {
status: 302,
headers: {
Location: `${redirectURL}?success=true&integrationName=${encodeURIComponent(
integrationDefinition.name,
)}`,
},
});
} catch (error: any) {
logger.error("MCP OAuth callback error:", error);
return new Response(null, {
status: 302,
headers: {
Location: `${redirectURL}?success=false&error=${encodeURIComponent(
error.message || "OAuth callback failed",
)}`,
},
});
}
}