core/apps/webapp/app/routes/api.v1.oauth.callback.mcp.tsx
Harshith Mullapudi 8d9ddcf375
Fix: core cli to work with core repo (#26)
* Fix: core cli to work with core repo

* Fix: cli working and mcp proxy
2025-07-22 10:17:40 +05:30

116 lines
3.3 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";
import {
getIntegrationAccount,
getIntegrationAccountForId,
} from "~/services/integrationAccount.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,
userId,
workspaceId,
integrationAccountId,
} = 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,
);
const integrationAccount =
await getIntegrationAccountForId(integrationAccountId);
if (!integrationDefinition) {
throw new Error("Integration definition not found");
}
const spec = integrationDefinition.spec as any;
if (!spec.mcp) {
throw new Error("MCP auth configuration not found for this integration");
}
const { transportStrategy, url } = spec.mcp;
const authClient = createMCPAuthClient({
serverUrl: url,
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,
},
mcp: true,
},
},
// We need to get userId from somewhere - for now using undefined
userId,
workspaceId,
integrationAccount ?? 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",
)}`,
},
});
}
}