# Connect AI agent frameworks to the OmniSocials MCP server

> Index of all OmniSocials docs pages: https://docs.omnisocials.com/llms.txt

Agents you build in code can use the hosted OmniSocials MCP server, the same server that claude.ai and ChatGPT connect to. The agent gets tools like `list_accounts`, `create_post`, `upload_media`, `get_best_times`, and the inbox and analytics tools. See [MCP server](https://docs.omnisocials.com/mcp-server.md) for the full list.

This page has a minimal working sample for each framework:

- [OpenAI Agents SDK](#openai-agents-sdk-python) (Python)
- [Vercel AI SDK](#vercel-ai-sdk-typescript) (TypeScript)
- [LangChain and LangGraph](#langchain-and-langgraph-python) (Python)
- [Mastra](#mastra-typescript) (TypeScript)
- [CrewAI](#crewai-python) (Python)

## Connection details

| Setting | Value |
|---------|-------|
| URL | `https://mcp.omnisocials.com` |
| Transport | Streamable HTTP. There is no SSE endpoint. |
| Authentication | `Authorization: Bearer omsk_live_<YOUR_KEY>` |

Use the URL as it is. Do not add `/mcp` or `/sse` to it.

**How the key works.** The server reads any bearer token that starts with `omsk_` as an OmniSocials API key. That makes the `Authorization` header the right choice for server-side code. The `?API_KEY=` query form on the [MCP server](https://docs.omnisocials.com/mcp-server.md) page also works, but a header keeps the key out of URLs and request logs. OAuth is meant for apps where a person signs in, see [OAuth for your users](#oauth-for-your-users).

**Protocol version.** The server uses the MCP initialize handshake. Clients built for the newer `2026-07-28` revision, such as current FastMCP, Mastra, and the AI SDK, probe for it first and fall back to the handshake on their own. Leave their protocol setting on its default. A client pinned to `2026-07-28` only will not connect.

## Before you start

1. Create an API key in **Settings → API**. For an agent that drafts and schedules posts, give it `posts:write`, `media:write`, and `accounts:read`. Add `analytics:read` if it should read results. See [Authentication](https://docs.omnisocials.com/authentication.md).
2. Store the key in an environment variable or your secrets manager. Never commit it.

```bash
export OMNISOCIALS_API_KEY="omsk_live_<YOUR_KEY>"
```

The samples below read `OMNISOCIALS_API_KEY` and also need your model provider's key, as each framework documents.

## OpenAI Agents SDK (Python)

The Agents SDK connects to remote servers with `MCPServerStreamableHttp`.

```bash
pip install openai-agents
```

```python
import asyncio
import os

from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp

async def main() -> None:
    async with MCPServerStreamableHttp(
        name="OmniSocials",
        params={
            "url": "https://mcp.omnisocials.com",
            "headers": {"Authorization": f"Bearer {os.environ['OMNISOCIALS_API_KEY']}"},
            "timeout": 30,
        },
        cache_tools_list=True,
        client_session_timeout_seconds=60,
    ) as server:
        agent = Agent(
            name="Social media assistant",
            instructions=(
                "Use the OmniSocials tools. Call list_accounts before you create a post. "
                "Create drafts unless the user asks you to schedule or publish."
            ),
            mcp_servers=[server],
        )
        result = await Runner.run(agent, "Draft a LinkedIn post about our new pricing page.")
        print(result.final_output)

asyncio.run(main())
```

`client_session_timeout_seconds` defaults to 5 seconds. Raise it as above, because uploading media from a URL can take longer.

## Vercel AI SDK (TypeScript)

The AI SDK's MCP client is `createMCPClient` from `@ai-sdk/mcp`.

```bash
npm install ai @ai-sdk/mcp
```

```typescript
import { createMCPClient, type MCPClient } from '@ai-sdk/mcp';
import { generateText, isStepCount } from 'ai';

let mcpClient: MCPClient | undefined;

try {
  mcpClient = await createMCPClient({
    transport: {
      type: 'http',
      url: 'https://mcp.omnisocials.com',
      headers: { Authorization: `Bearer ${process.env.OMNISOCIALS_API_KEY}` },
    },
  });

  const tools = await mcpClient.tools();

  const { text } = await generateText({
    model: 'anthropic/claude-sonnet-5.5',
    tools,
    stopWhen: isStepCount(5),
    prompt: 'List my connected social accounts, then draft a LinkedIn post about our new pricing page.',
  });

  console.log(text);
} finally {
  await mcpClient?.close();
}
```

`generateText` runs one step by default. `stopWhen: isStepCount(5)` lets the model call a tool, read the result, and continue. With `streamText`, close the client in `onEnd` instead.

## LangChain and LangGraph (Python)

LangChain 1.4 ships MCP support in `langchain.mcp` (beta). It replaces the standalone `langchain-mcp-adapters` package, which is no longer actively maintained. Both work with OmniSocials. Use the first tab for new projects.

```python title="langchain.mcp"
# pip install "langchain[mcp]"
import asyncio
import os

from fastmcp.client import Client
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter

async def main():
    client = Client("https://mcp.omnisocials.com", auth=os.environ["OMNISOCIALS_API_KEY"])
    async with MCPAdapter(client) as adapter:
        tools = await adapter.list_tools()
        agent = create_agent("claude-sonnet-5", tools)
        result = await agent.ainvoke(
            {"messages": [{"role": "user", "content": "List my connected social accounts."}]}
        )
        print(result["messages"][-1].content)

asyncio.run(main())
```

```python title="langchain-mcp-adapters"
# pip install langchain-mcp-adapters
import asyncio
import os

from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient

async def main():
    client = MultiServerMCPClient(
        {
            "omnisocials": {
                "transport": "http",
                "url": "https://mcp.omnisocials.com",
                "headers": {"Authorization": f"Bearer {os.environ['OMNISOCIALS_API_KEY']}"},
            }
        }
    )
    tools = await client.get_tools()
    agent = create_agent("claude-sonnet-5", tools)
    result = await agent.ainvoke({"messages": "List my connected social accounts."})
    print(result["messages"][-1].content)

asyncio.run(main())
```

In `langchain.mcp`, the key goes on the FastMCP `Client` as `auth`. A plain string there is sent as a bearer token. `create_agent` returns a LangGraph graph. In a graph you build yourself, give the same `tools` list to your tool node.

## Mastra (TypeScript)

Mastra connects with `MCPClient` from `@mastra/mcp`. Version 2 of `@mastra/mcp` needs `@mastra/core` 1.76 or a later 1.x release.

```bash
npm install @mastra/mcp@latest @mastra/core
```

```typescript
import { Agent } from '@mastra/core/agent';
import { MCPClient } from '@mastra/mcp';

export const omnisocials = new MCPClient({
  id: 'omnisocials',
  servers: {
    omnisocials: {
      url: new URL('https://mcp.omnisocials.com'),
      requestInit: {
        headers: { Authorization: `Bearer ${process.env.OMNISOCIALS_API_KEY}` },
      },
    },
  },
});

export const socialAgent = new Agent({
  id: 'social-agent',
  name: 'Social media assistant',
  instructions: 'Use the OmniSocials tools. List the accounts before you create a post.',
  model: 'openai/gpt-5.6-sol',
  tools: await omnisocials.listTools(),
});

const response = await socialAgent.generate('List my connected social accounts.');
console.log(response.text);
```

`listTools()` prefixes every tool with the server key, so the agent sees `omnisocials_list_accounts` and `omnisocials_create_post`.

If each of your users has their own OmniSocials key, build an `MCPClient` per request and pass `await client.listToolsets()` as `toolsets` to `generate()` instead of setting `tools` on the agent. Call `disconnect()` on that client when the request is done.

## CrewAI (Python)

CrewAI agents take MCP servers in their `mcps` field. `MCPServerHTTP` from `crewai.mcp` speaks Streamable HTTP.

```bash
uv add crewai mcp
```

```python
import os

from crewai import Agent, Crew, Task
from crewai.mcp import MCPServerHTTP

social_agent = Agent(
    role="Social media manager",
    goal="Plan and schedule posts on the company's social accounts",
    backstory="You run the company's social media through OmniSocials.",
    mcps=[
        MCPServerHTTP(
            url="https://mcp.omnisocials.com",
            headers={"Authorization": f"Bearer {os.environ['OMNISOCIALS_API_KEY']}"},
            streamable=True,
        ),
    ],
)

task = Task(
    description="List the connected social accounts, then draft a LinkedIn post about our new pricing page.",
    expected_output="The connected accounts and the ID of the draft post.",
    agent=social_agent,
)

crew = Crew(agents=[social_agent], tasks=[task])
print(crew.kickoff())
```

## Keep agents in bounds

An agent with `posts:write` can publish to your real accounts. There is no test mode.

- Give each agent its own key with only the scopes it needs. A missing scope makes the tool return `403`.
- Ask the agent to create drafts, which a person reviews and schedules in the dashboard. Or have it pass an `approval_workflow_id` to `create_post`, so the post waits for an approver. `list_approval_workflows` lists the workflows.
- Gate the tools that publish or delete, such as `publish_post`, `create_and_publish_post`, and `delete_post`. The frameworks have hooks for this: `tool_filter` and `require_approval` in the OpenAI Agents SDK, `toolApproval` in the AI SDK, `requireToolApproval` in Mastra, and `@wrap_tool_call` middleware in LangChain.

## OAuth for your users

If people sign in to your app with their own OmniSocials account, use OAuth instead of a shared key. The server supports OAuth with dynamic client registration, and the user picks which workspaces your app may use. Each framework has its own OAuth hook: `auth="oauth"` on the FastMCP `Client`, `authProvider` on the AI SDK transport, and `authProvider` with `MCPOAuthClientProvider` in Mastra. Follow the framework's OAuth guide with `https://mcp.omnisocials.com` as the server URL.

## Troubleshooting

| Symptom | Cause | Fix |
|---------|-------|-----|
| `401` on connect | The key is wrong or revoked, or the header lacks `Bearer `. | Check the `Authorization` header value. |
| `402` on connect | The organisation has no active plan. | Check billing in **Settings → Organisation**. |
| `404` with "Session expired" | The server dropped the session, for example after a restart. | Reconnect. Most clients send a new initialize on their own. |
| A tool call returns `403` | The key misses that tool's scope. | Create a new key with the scope. Scopes cannot be edited. |
| The client cannot connect at all | It uses the old SSE transport, or `/mcp` or `/sse` was added to the URL. | Use the Streamable HTTP class shown above and the bare URL. |
