FabricFabricSDK

Framework adapters

Use the Integrations SDK with Vercel AI SDK, OpenAI, Anthropic, and Cursor.

The Integrations SDK exposes plugins as typed endpoint treesfabric.slack.api.messages.send(...), fabric.stripe.api.customers.create(...), etc. Every major AI framework can call these endpoints via its native tool/function-calling pattern.

Vercel AI SDK

Use streamText or useChat with tool() definitions that delegate to Fabric endpoints.

import { streamText, tool } from "ai";
import { createFabric } from "@fabricorg/integrations";
import { slack, stripe } from "@fabricorg/integrations/plugins";
import { openai } from "@ai-sdk/openai";

const fabric = createFabric({
  plugins: [
    slack({ botToken: process.env.SLACK_BOT_TOKEN }),
    stripe({ apiKey: process.env.STRIPE_SECRET_KEY }),
  ],
});

const result = streamText({
  model: openai("gpt-4o"),
  tools: {
    slackSendMessage: tool({
      description: "Send a message to a Slack channel",
      parameters: z.object({ channel: z.string(), text: z.string() }),
      execute: async ({ channel, text }) =>
        fabric.slack.api.messages.send({ channel, text }),
    }),
    stripeGetCustomer: tool({
      description: "Get a Stripe customer by ID",
      parameters: z.object({ id: z.string() }),
      execute: async ({ id }) => fabric.stripe.api.customers.get({ id }),
    }),
  },
  prompt: "Send a welcome message to #general and look up customer cus_123",
});

The execute function is a standard async function — it can call any Fabric endpoint, use hooks, or chain multiple calls.

OpenAI function calling

OpenAI's tools array maps naturally to Fabric endpoints.

import OpenAI from "openai";
import { createFabric } from "@fabricorg/integrations";
import { github } from "@fabricorg/integrations/plugins";

const fabric = createFabric({
  plugins: [github({ token: process.env.GITHUB_TOKEN })],
});

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const completion = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [
    { role: "user", content: "List open issues in fabricorg/integrations" },
  ],
  tools: [
    {
      type: "function",
      function: {
        name: "github_issues_list",
        description: "List issues in a GitHub repository",
        parameters: {
          type: "object",
          properties: {
            owner: { type: "string" },
            repo: { type: "string" },
            state: { type: "string", enum: ["open", "closed", "all"] },
          },
          required: ["owner", "repo"],
        },
      },
    },
  ],
});

// Execute the tool call
const call = completion.choices[0].message.tool_calls?.[0];
if (call?.function.name === "github_issues_list") {
  const args = JSON.parse(call.function.arguments);
  const issues = await fabric.github.api.issues.list(args);
  console.log(issues);
}

Anthropic SDK

Anthropic's native tool use works the same way — define tools that wrap Fabric endpoints.

import Anthropic from "@anthropic-ai/sdk";
import { createFabric } from "@fabricorg/integrations";
import { notion } from "@fabricorg/integrations/plugins";

const fabric = createFabric({
  plugins: [notion({ apiKey: process.env.NOTION_API_KEY })],
});

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

const message = await anthropic.messages.create({
  model: "claude-sonnet-4-5-20251001",
  max_tokens: 1024,
  tools: [
    {
      name: "notion_pages_create",
      description: "Create a new Notion page",
      input_schema: {
        type: "object",
        properties: {
          parent: {
            type: "object",
            properties: {
              database_id: { type: "string" },
            },
          },
          properties: { type: "object" },
        },
        required: ["parent", "properties"],
      },
    },
  ],
  messages: [
    { role: "user", content: "Create a Notion page titled 'Q2 Planning' in database abc123" },
  ],
});

// Execute tool use
const toolUse = message.content.find((c) => c.type === "tool_use");
if (toolUse?.name === "notion_pages_create") {
  const page = await fabric.notion.api.pages.create(toolUse.input as never);
  console.log(page.url);
}

Cursor / Claude Desktop

The Portal SDK (@fabric/mcp-server) is the native integration for Cursor and Claude Desktop. Add it to your MCP config:

{
  "mcpServers": {
    "fabric": {
      "command": "fabric-mcp",
      "env": {
        "FABRIC_API_KEY": "fab_...",
        "FABRIC_API_URL": "https://app.fabric.pro"
      }
    }
  }
}

For Integrations SDK access inside Cursor, you have two options:

Option 1: Custom MCP server

Build a small MCP server that wraps your Fabric instance:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { createFabric } from "@fabricorg/integrations";
import { slack, github } from "@fabricorg/integrations/plugins";

const fabric = createFabric({
  plugins: [
    slack({ botToken: process.env.SLACK_BOT_TOKEN }),
    github({ token: process.env.GITHUB_TOKEN }),
  ],
});

const server = new Server(
  { name: "fabric-integrations", version: "1.0.0" },
  {
    capabilities: {
      tools: {
        slack_send: {
          description: "Send a Slack message",
          inputSchema: {
            type: "object",
            properties: {
              channel: { type: "string" },
              text: { type: "string" },
            },
            required: ["channel", "text"],
          },
        },
      },
    },
  },
);

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "slack_send") {
    const { channel, text } = request.params.arguments as { channel: string; text: string };
    const result = await fabric.slack.api.messages.send({ channel, text });
    return { content: [{ type: "text", text: JSON.stringify(result) }] };
  }
  throw new Error(`Unknown tool: ${request.params.name}`);
});

const transport = new StdioServerTransport();
await server.connect(transport);

Option 2: Via Portal SDK

Use the Portal SDK's fabric_chat_with_agent tool to trigger an agent that has Integrations SDK access. The agent's runtime includes the plugins, so you drive integrations conversationally through the portal.

Type safety across frameworks

All Fabric endpoints are fully typed. When you define a tool wrapper, TypeScript checks that your parameter schema matches the endpoint's input shape:

// Type error: 'channl' does not exist in Slack message input
fabric.slack.api.messages.send({ channl: "C01", text: "hi" });
//                                 ^^^^^^

This type safety propagates to your AI framework's tool definitions — keep the Zod schemas or JSON schemas in sync with the endpoint types for end-to-end validation.