本文へ移動
cccskills
無料GitHub で公開

add-oauth-integration

Guide for adding new OAuth-based integrations to Fabric. Use when implementing OAuth providers like Microsoft Teams, GitHub, Google Drive, Slack, or similar services that need OAuth 2.0 authentication for user data access.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md20.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Add OAuth Integration Skill

This skill guides you through adding a new OAuth-based integration to the Fabric platform.

When to Use This Skill

  • Adding a new OAuth provider (Microsoft Teams, Slack, Notion, etc.)
  • Connecting third-party services via OAuth 2.0 flow
  • Creating MCP tools that require user authentication
  • Building integrations that access external APIs on behalf of users

Overview

OAuth integrations allow users to connect third-party services using OAuth 2.0 flow. Credentials are stored server-side (encrypted), not in the browser. The integration appears in the Fabric AI Agent's available tools.

Architecture Overview

User clicks "Connect" → OAuth popup → Provider auth → Callback stores token
                                                            ↓
                                                   WorkflowIntegration table
                                                            ↓
                        ┌───────────────────────────────────┴───────────────────────────────────┐
                        ↓                                                                       ↓
              TASK AGENT PATH                                                      ORCHESTRATOR PATH
         (Custom agents: /app/agents/{id})                                 (Fabric AI: /app/agents/fabric-ai)
                        ↓                                                                       ↓
         mcp-tools.ts → loadMcpConfiguration                               preload-resources.ts → loadOAuthIntegrationTools
         agent-execution.ts → workflow guidance                            initialization.ts → passes enabledIntegrationIds

⚠️ CRITICAL: Two Code Paths

OAuth integrations must be implemented in BOTH code paths:

PathInterfaceWhen UsedKey Files
Task Agent/app/agents/{agentId}Custom registered agentsmcp-tools.ts, agent-execution.ts
Orchestrator/app/agents/fabric-aiFabric AI Agent (main interface)preload-resources.ts, initialization.ts

If you only implement the Task Agent path, your integration will NOT work in Fabric AI Agent!

Files to Update (Checklist)

1. OAuth Provider Configuration

File: packages/api/modules/integrations/lib/oauth-providers.ts

// 1. Add to OAuthProviderType union
export type OAuthProviderType =
	| "GITHUB"
	| "GOOGLE_DRIVE"
	| "MICROSOFT_GRAPH"  // Microsoft Teams uses this
	| "SLACK"
	| "NOTION"
	| "YOUR_NEW_PROVIDER"; // Add here

// 2. Create provider config
const yourNewProvider: OAuthProviderConfig = {
	type: "YOUR_NEW_PROVIDER",
	name: "Your Provider Display Name", // IMPORTANT: This name is returned in OAuth callback
	authorizationUrl: "https://provider.com/oauth/authorize",
	tokenUrl: "https://provider.com/oauth/token",
	scopes: ["scope1", "scope2"],
	clientIdEnvVar: "YOUR_PROVIDER_CLIENT_ID",
	clientSecretEnvVar: "YOUR_PROVIDER_CLIENT_SECRET",
	supportsRefreshToken: true, // or false
	authParams: { // optional
		access_type: "offline",
	},
	getUserInfo: async (accessToken: string): Promise<OAuthUserInfo> => {
		const response = await fetch("https://api.provider.com/user", {
			headers: { Authorization: `Bearer ${accessToken}` },
		});
		const data = await response.json();
		return {
			id: data.id,
			login: data.username,
			name: data.displayName,
			email: data.email,
			avatarUrl: data.avatar,
		};
	},
	refreshAccessToken: async (refreshToken, clientId, clientSecret) => {
		// Implement if supportsRefreshToken is true
	},
};

// 3. Add to oauthProviders record
export const oauthProviders: Record<OAuthProviderType, OAuthProviderConfig> = {
	// ... existing providers
	YOUR_NEW_PROVIDER: yourNewProvider,
};

2. MCP Registry - Workflow Guidance

File: packages/mcp-registry/src/workflow-guidance.ts

Add workflow guidance so the AI knows how to use your tools:

export const YOUR_PROVIDER_WORKFLOW_GUIDANCE = `## Your Provider Workflow

When user asks about Your Provider data:
1. Use your_provider__list_items to get available items
2. Use your_provider__get_item for specific item details
3. Use your_provider__search for searching

### Example Usage
- "Show me my items" → your_provider__list_items
- "Search for X" → your_provider__search({ query: "X" })
`;

3. MCP Registry - Conditional Account

File: packages/mcp-registry/src/conditional-accounts.ts

Define the account and its tools:

export const YOUR_PROVIDER_ACCOUNT: AccountDefinition = {
	id: "your_provider",
	name: "Your Provider",
	credentialType: "your_provider_oauth",
	authType: "oauth",
	requiredScopes: ["scope1", "scope2"],
	mcps: [
		{
			id: "your-provider-tools",
			name: "Your Provider Tools",
			serverName: "your_provider",
			available: true,
			tools: [
				{
					name: "list_items",
					description: "List all items from Your Provider",
					inputSchema: {
						type: "object",
						properties: {
							limit: { type: "number", description: "Max items to return" },
						},
					},
				},
				// ... more tools
			],
		},
	],
};

// Add to CONDITIONAL_ACCOUNTS array
export const CONDITIONAL_ACCOUNTS: AccountDefinition[] = [
	GITHUB_ACCOUNT,
	MICROSOFT_TEAMS_ACCOUNT,
	YOUR_PROVIDER_ACCOUNT, // Add here
];

4. MCP Registry - Exports

File: packages/mcp-registry/src/index.ts

// Export workflow guidance
export {
	// ... existing exports
	YOUR_PROVIDER_WORKFLOW_GUIDANCE,
} from "./workflow-guidance";

// Export account
export {
	// ... existing exports
	YOUR_PROVIDER_ACCOUNT,
} from "./conditional-accounts";

5. Tool Execution in Temporal

File: packages/temporal/src/activities/task-agent/mcp-tools.ts

Add tool execution handler:

// 1. Add check in executeTaskAgentTool
if (mcpTool.configId.startsWith("your-provider-connected:")) {
	const methodName = toolName.split("__")[1] || toolName;
	return executeYourProviderTool(methodName, args, userId, organizationId);
}

// 2. Implement the execution function
async function executeYourProviderTool(
	methodName: string,
	args: Record<string, unknown>,
	userId: string,
	organizationId?: string,
): Promise<unknown> {
	// Get token from WorkflowIntegration (uses XOR pattern)
	const integration = organizationId
		? await db.workflowIntegration.findFirst({
				where: { organizationId, provider: "YOUR_PROVIDER", isActive: true },
			})
		: await db.workflowIntegration.findFirst({
				where: { userId, organizationId: null, provider: "YOUR_PROVIDER", isActive: true },
			});

	if (!integration?.credentials) {
		throw new Error("Provider not connected. Please connect in Settings > Integrations.");
	}

	const credentialsJson = decryptApiKey(integration.credentials);
	const { access_token } = JSON.parse(credentialsJson);

	// Call provider API based on methodName
	switch (methodName) {
		case "list_items":
			// Implement API call
			break;
		// ... more cases
	}
}

// 3. Add conditional loading in loadMcpConfiguration
const yourProviderIntegration = organizationId
	? await db.workflowIntegration.findFirst({
			where: { organizationId, provider: "YOUR_PROVIDER", isActive: true },
		})
	: await db.workflowIntegration.findFirst({
			where: { userId, organizationId: null, provider: "YOUR_PROVIDER", isActive: true },
		});

if (yourProviderIntegration) {
	const { YOUR_PROVIDER_ACCOUNT } = await import("@repo/mcp-registry");
	// Add tools from YOUR_PROVIDER_ACCOUNT.mcps
}

6. Agent Execution - Add Workflow Guidance

File: packages/temporal/src/activities/task-agent/agent-execution.ts

// 1. Import the guidance
import {
	GITHUB_WORKFLOW_GUIDANCE,
	MICROSOFT_TEAMS_WORKFLOW_GUIDANCE,
	YOUR_PROVIDER_WORKFLOW_GUIDANCE, // Add import
	getAlwaysEnabledWorkflowGuidance,
} from "@repo/mcp-registry";

// 2. Check if tools are connected
const hasYourProviderConnected = mcpConfig.tools.some((t) =>
	t.configId.startsWith("your-provider-connected:"),
);

// 3. Add guidance in buildAgentSystemPrompt
if (hasYourProviderConnected && YOUR_PROVIDER_WORKFLOW_GUIDANCE) {
	workflowGuidance = workflowGuidance
		? `${workflowGuidance}\n\n${YOUR_PROVIDER_WORKFLOW_GUIDANCE}`
		: YOUR_PROVIDER_WORKFLOW_GUIDANCE;
}

7. Orchestrator Path - Preload Resources (CRITICAL!)

File: packages/temporal/src/activities/orchestrator/preload/preload-resources.ts

This is the most commonly missed step. Without this, your integration works in custom agents but NOT in Fabric AI Agent.

// In loadOAuthIntegrationTools function, add a new block for your provider:

// ========== YOUR PROVIDER Integration ==========
const yourProviderIntegration = await db.oAuthIntegration.findFirst({
	where: {
		userId,
		organizationId: organizationId ?? null,
		provider: "your_provider", // lowercase provider name
	},
});

if (yourProviderIntegration?.accessToken) {
	// Check if enabled via direct integrationIds OR prefixed filterIds
	const newFormatId = `oauth:your_provider:${yourProviderIntegration.id}`;
	const legacyFormatId = `oauth:yourprovider:${yourProviderIntegration.id}`; // if applicable

	// CRITICAL: Check BOTH formats - UI may pass either one
	const isEnabledViaIntegrationIds = integrationIds
		? integrationIds.includes(yourProviderIntegration.id)
		: false;
	const isEnabledViaFilterIds = filterIds
		? filterIds.includes(newFormatId) ||
		  filterIds.includes(legacyFormatId) ||
		  filterIds.includes(yourProviderIntegration.id)
		: false;

	// If no filter specified at all, allow all (backward compatibility)
	const noFiltersSpecified = !filterIds && !integrationIds;
	const isEnabled = noFiltersSpecified || isEnabledViaIntegrationIds || isEnabledViaFilterIds;

	if (!isEnabled) {
		console.log("[Preload] Your Provider integration disabled in orchestrator preferences");
	} else {
		try {
			const { YOUR_PROVIDER_ACCOUNT } = await import("@repo/mcp-registry");

			let toolCount = 0;
			for (const mcp of YOUR_PROVIDER_ACCOUNT.mcps) {
				if (mcp.available === false) {
					continue;
				}

				const serverName = mcp.serverName || mcp.name;
				const tools: McpToolInfo[] = [];

				for (const tool of mcp.tools || []) {
					const toolName = `${serverName}__${tool.name}`;
					tools.push({
						name: toolName,
						description: tool.description || "",
						inputSchema: (tool.inputSchema as Record<string, unknown>) || {
							type: "object",
						},
					});
					toolCount++;
				}

				if (tools.length > 0) {
					results.push({
						serverId: `your-provider-connected:${yourProviderIntegration.id}`,
						serverName,
						tools,
						serverType: "oauth",
					});
				}
			}

			console.log(`[Preload] Loaded ${toolCount} Your Provider tools from registry`);
		} catch (e) {
			console.warn("[Preload] Failed to load Your Provider tools from registry", e);
		}
	}
}

8. Orchestrator Path - Initialization Phase

File: packages/temporal/src/workflows/orchestrator/phases/initialization.ts

Ensure enabledIntegrationIds is passed to the preload activity:

// In executeInitializationPhase function:
const preloadedResources = await preloadResourcesActivity({
	userId: input.userId,
	organizationId: input.organizationId,
	enabledMcpConfigIds: input.enabledMcpConfigIds ?? undefined,
	enabledAgentIds: input.enabledAgentIds ?? undefined,
	enabledIntegrationIds: input.enabledIntegrationIds ?? undefined, // CRITICAL: Don't forget this!
});

Also verify that PreloadResourcesInput interface includes enabledIntegrationIds:

export interface PreloadResourcesInput {
	userId: string;
	organizationId?: string;
	enabledMcpConfigIds?: string[];
	enabledAgentIds?: string[];
	enabledIntegrationIds?: string[];  // Must be present!
}

Part 2: UI and Configuration

9. Plugin UI Components

Directory: apps/web/modules/saas/workflows/lib/plugins/your-provider/

Create these files:

icon.tsx

export function YourProviderIcon({ className }: { className?: string }) {
	return (
		<svg className={className} viewBox="0 0 24 24" fill="currentColor">
			{/* SVG path */}
		</svg>
	);
}

YourProviderSettings.tsx

"use client";

import { OAuthSettings } from "../shared/OAuthSettings";
import { YourProviderIcon } from "./icon";
import type { IntegrationSettingsProps } from "../types";

export function YourProviderSettings({
	onApiKeyChange,
	organizationId,
}: IntegrationSettingsProps) {
	return (
		<OAuthSettings
			provider="YOUR_NEW_PROVIDER"
			// CRITICAL: This MUST match exactly the 'name' field in oauth-providers.ts
			providerName="Your Provider Display Name"
			providerIcon={YourProviderIcon}
			providerColor="text-blue-600"
			description="Connect your account to access data."
			helpText="We request read-only access to your data."
			scopes={["scope1", "scope2"]}
			organizationId={organizationId}
			onConnectionChange={(connected) => {
				if (connected) {
					onApiKeyChange("oauth_connected");
				} else {
					onApiKeyChange("");
				}
			}}
		/>
	);
}

index.ts

import { registerIntegration } from "../registry";
import type { IntegrationPlugin } from "../types";
import { YourProviderIcon } from "./icon";
import { YourProviderSettings } from "./YourProviderSettings";

export const yourProviderPlugin: IntegrationPlugin = {
	type: "YOUR_NEW_PROVIDER",
	label: "Your Provider",
	description: "Access your provider's data for AI-powered workflows",
	icon: YourProviderIcon,
	color: "text-blue-600",
	formFields: [],
	SettingsComponent: YourProviderSettings,
	testConfig: { skipClientTest: true },
	actions: [
		{ id: "list_items", label: "List Items", description: "Get all items" },
		// ... more actions
	],
};

registerIntegration(yourProviderPlugin);
export default yourProviderPlugin;

8. Register Plugin

File: apps/web/modules/saas/workflows/lib/plugins/index.ts

import "./your-provider";
export { yourProviderPlugin } from "./your-provider";

9. Environment Variables

File: .env.example and .env.local

YOUR_PROVIDER_CLIENT_ID="your-client-id"
YOUR_PROVIDER_CLIENT_SECRET="your-client-secret"

Testing the Integration

Important: Use Fabric AI Agent, NOT Basic Chat

MCP tools are only available in the Fabric AI Agent interface, not the basic AI Chat.

Step 1: Set Environment Variables

# .env.local
YOUR_PROVIDER_CLIENT_ID="your-actual-client-id"
YOUR_PROVIDER_CLIENT_SECRET="your-actual-client-secret"

Step 2: Restart Development Server

pnpm dev
# OR if using Aspire:
./aspire.sh restart

Step 3: Connect the Integration

  1. Go to Settings > Integrations (or /app/settings/integrations)
  2. Find your provider in the list
  3. Click Connect with [Provider]
  4. Complete OAuth flow in popup
  5. Verify "Connected" status appears

Step 4: Test Tools in Fabric AI Agent

  1. Navigate to Fabric AI Agent: /app/agents/fabric-ai
    • Or for organization: /app/{org-slug}/agents/fabric-ai
  2. Try prompts that use your tools:
    Show me my items from [Provider]
    Search [Provider] for "keyword"
    

Step 5: Verify Tool Execution

Check Temporal worker logs for:

  • Tool calls to your_provider__*
  • API requests to your provider

Common Pitfalls

1. Missing Orchestrator Path (CRITICAL!)

Problem: Integration works in custom agents (/app/agents/{id}) but NOT in Fabric AI Agent (/app/agents/fabric-ai).

Cause: You only implemented the Task Agent path and forgot the Orchestrator path.

Solution: Add your integration to BOTH:

  1. packages/temporal/src/activities/task-agent/mcp-tools.ts (Task Agent)
  2. packages/temporal/src/activities/orchestrator/preload/preload-resources.ts (Orchestrator)

See sections 7-8 above for the Orchestrator implementation.

2. enabledIntegrationIds Not Passed Through

Problem: Integration is connected and enabled in UI, but tools don't load in Fabric AI Agent.

Cause: enabledIntegrationIds isn't being passed from workflow input to preload activity.

Solution: Check initialization.ts passes enabledIntegrationIds:

const preloadedResources = await preloadResourcesActivity({
	// ...other params
	enabledIntegrationIds: input.enabledIntegrationIds ?? undefined,
});

3. Integration ID Format Mismatch

Problem: Integration shows as enabled in UI but preload function says "disabled in preferences".

Cause: The UI may pass IDs in different formats:

  • Direct: "integration-uuid-here"
  • Prefixed: "oauth:provider:integration-uuid-here"

Solution: Check BOTH formats in your enable check:

const isEnabledViaIntegrationIds = integrationIds?.includes(integration.id) ?? false;
const isEnabledViaFilterIds = filterIds
	? filterIds.includes(`oauth:provider:${integration.id}`) ||
	  filterIds.includes(integration.id)
	: false;

4. Provider Name Mismatch

Problem: After OAuth completes, UI doesn't update to show connected state.

Cause: The providerName in your Settings component doesn't match the name field in oauth-providers.ts.

Solution: Ensure exact match:

// oauth-providers.ts
const provider = { name: "Microsoft 365" };

// Settings component - MUST MATCH!
<OAuthSettings providerName="Microsoft 365" ... />

5. "OAuth not configured on server"

Problem: Integration shows this message instead of Connect button.

Solution:

  1. Check env vars are set in .env.local
  2. Restart the dev server (env vars are loaded at startup)

6. Tools Not Appearing in Fabric AI Agent

Problem: Connected but AI doesn't use your tools.

Causes & Solutions:

  1. Missing Orchestrator path: Add to preload-resources.ts (most common!)
  2. Missing from loadMcpConfiguration: Add conditional loading check in Task Agent path
  3. Missing workflow guidance: Add guidance to agent-execution.ts
  4. Using wrong interface: Use Fabric AI Agent (/app/agents/fabric-ai), not basic Chat

7. Tool Execution Fails

Problem: AI tries to use tool but gets error.

Solutions:

  1. Check executeYourProviderTool function exists in mcp-tools.ts
  2. Check configId prefix matches (your-provider-connected:)
  3. Verify WorkflowIntegration record exists with correct provider enum

8. Tenant Isolation Issues

Problem: Personal credentials used in org context or vice versa.

Solution: Always use XOR pattern in queries:

// For org context
{ organizationId, provider: "...", isActive: true }

// For personal context - explicitly check null!
{ userId, organizationId: null, provider: "...", isActive: true }

Testing Checklist

  • Environment variables set in .env.local
  • Dev server restarted
  • Integration appears in Settings > Integrations
  • OAuth Connect button shows (not "not configured")
  • OAuth flow completes successfully
  • UI shows "Connected" status
  • Task Agent path: Tools load in custom agents (/app/agents/{id})
  • Orchestrator path: Tools load in Fabric AI Agent (/app/agents/fabric-ai)
  • Enable/disable toggle in Orchestrator preferences works
  • AI can execute tools successfully
  • Test in both personal AND organization contexts

Example: Microsoft Teams Integration

For reference, see the Microsoft Teams implementation:

ComponentFile
OAuth Providerpackages/api/modules/integrations/lib/oauth-providers.ts → microsoftGraphProvider
Workflow Guidancepackages/mcp-registry/src/workflow-guidance.ts → MICROSOFT_TEAMS_WORKFLOW_GUIDANCE
Account Definitionpackages/mcp-registry/src/conditional-accounts.ts → MICROSOFT_TEAMS_ACCOUNT
Task Agent Path
Tool Executionpackages/temporal/src/activities/task-agent/mcp-tools.ts → executeMicrosoftTeamsTool
Agent Guidancepackages/temporal/src/activities/task-agent/agent-execution.ts
Orchestrator Path
Preload Resourcespackages/temporal/src/activities/orchestrator/preload/preload-resources.ts → loadOAuthIntegrationTools
Initializationpackages/temporal/src/workflows/orchestrator/phases/initialization.ts → passes enabledIntegrationIds
UI
UI Pluginapps/web/modules/saas/workflows/lib/plugins/microsoft-teams/

Debugging Tips

Check if OAuth is configured

// Temporary logging in oauth.ts isConfigured handler
console.log("[OAuth] Provider:", provider.name, "clientId exists:", !!clientId);

Verify tools are loaded

In browser console on Fabric AI Agent page, check for tool loading logs.

Check WorkflowIntegration record

SELECT * FROM "WorkflowIntegration"
WHERE provider = 'YOUR_PROVIDER' AND "isActive" = true;

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Build accessible web applications following WCAG 2.1/2.2 guidelines with proper semantic HTML, ARIA attributes, keyboard navigation, screen reader support, and inclusive design. Use when implementing ARIA labels and roles, ensuring keyboard navigation, supporting screen readers, providing text alternatives for images, managing focus, creating accessible forms, building inclusive UI components, testing with accessibility tools, meeting WCAG compliance levels, or designing for users with disabilities.

日本語の概要は準備中です。原文の説明を表示しています。

Fabric-Pro/fabric-oss32026年10月9日 更新

Design clean, scalable, and maintainable REST and GraphQL APIs following industry best practices. Use when designing public or internal APIs, planning endpoint structures, defining request/response contracts, establishing versioning strategies, implementing authentication patterns, designing data models, creating API documentation, ensuring consistent error handling, optimizing for performance, or establishing service contracts between microservices.

日本語の概要は準備中です。原文の説明を表示しています。

Fabric-Pro/fabric-oss32026年10月9日 更新

Create professional, dark-themed architecture diagrams as standalone HTML files with SVG graphics. Use when the user asks for system architecture diagrams, infrastructure diagrams, cloud architecture visualizations, security diagrams, network topology diagrams, or any technical diagram showing system components and their relationships.

日本語の概要は準備中です。原文の説明を表示しています。

Fabric-Pro/fabric-oss32026年10月9日 更新

Create interactive, self-contained artifacts like mini-apps, visualizations, calculators, and tools that can be embedded or used standalone. Use when building interactive calculators, creating data visualizations, making mini web apps, building embeddable widgets, creating interactive demos, making tools for specific tasks, or generating standalone HTML/JS applications.

日本語の概要は準備中です。原文の説明を表示しています。

Fabric-Pro/fabric-oss32026年10月9日 更新

Architect scalable backend services using layered architecture, dependency injection, middleware patterns, service classes, and separation of concerns. Use when building API services, implementing business logic layers, creating service classes, setting up middleware chains, implementing dependency injection, designing controller-service-repository patterns, handling cross-cutting concerns, creating domain models, implementing CQRS patterns, or establishing backend architecture standards.

日本語の概要は準備中です。原文の説明を表示しています。

Fabric-Pro/fabric-oss32026年10月9日 更新

Render Mermaid diagrams as SVG and PNG using the Beautiful Mermaid library. Use when the user asks to render a Mermaid diagram.

日本語の概要は準備中です。原文の説明を表示しています。

Fabric-Pro/fabric-oss32026年10月9日 更新

Fabric-Pro のスキルをすべて見る

このスキルの問題を報告する