← Discover MCPs and Agents
T
MCPAI & MLGitHub

ToolsConnector

Open-source Python library for 73 API connectors — Gmail, Slack, GitHub, Stripe, OpenAI, Anthropic & more. MCP server, OpenAI function calling, Anthropic tool use. 1,519 actions, 11 live-verified. Apache 2.0.

Links

README

From the repo.

ToolsConnector

One interface, every tool. Connect 68+ APIs to your Python app or AI agent in minutes.

PyPI version Python 3.9+ License: Apache 2.0 CI CodeQL Pydantic V2 PyPI downloads Typed


The Problem

Every SaaS API has its own SDK, its own auth dance, its own pagination scheme, and its own error format. If you're building an AI agent, you also need to generate JSON Schema for function calling -- differently for OpenAI, Anthropic, and Gemini. You end up writing glue code instead of product code.

ToolsConnector gives you a single, typed Python interface to 79 connectors and 1,650 actions. It works identically whether you're building a Django app, an OpenAI agent, or an MCP server for Claude Desktop.

Run the Documentation Site

To browse the full connector reference, playground, and guides locally:

python3 -m http.server 5001 --directory site

Then open http://localhost:5001 in your browser.


Install

pip install toolsconnector

Install only the connectors you need:

pip install "toolsconnector[gmail,slack,github]"

Or install a full category:

pip install "toolsconnector[communication,databases,mcp]"

Quick Start

from toolsconnector.serve import ToolKit

kit = ToolKit(
    ["gmail", "slack"],
    credentials={"gmail": "ya29.access-token", "slack": "xoxb-bot-token"},
)

# List unread emails
result = kit.execute("gmail_list_emails", {"query": "is:unread", "max_results": 5})

# Send a Slack message
kit.execute("slack_send_message", {"channel": "#general", "text": "Deployed v2.1"})

That's it. Same ToolKit, same .execute(), every connector.

Try the Examples

Want to see real integrations end-to-end? examples/ has 10 copy-pasteable scripts covering every major usage pattern. Pick one closest to what you want to build:

PatternScript
5-minute intro: ToolKit + execute01_basic_usage.py
One-line MCP server for Claude Desktop / Cursor02_mcp_server.py
OpenAI function-calling agent (full tool-use loop)03_openai_function_calling.py
Anthropic Claude tool-use agent04_anthropic_tool_use.py
Multi-connector agent with safety filtering05_multi_connector.py
tc CLI walkthrough06_cli_usage.sh
Multi-tenant ToolKitFactory (per-user isolation)07_multi_tenant.py
Expose connectors as REST API (Starlette + uvicorn)08_rest_api.py
CI health checks, spec extraction, OpenAPI export09_health_check.py
Publish to LinkedIn end-to-end10_linkedin_publish.py

See examples/README.md for the full table with required env vars.


Key Features

  • 79 connectors, 1,650 actions across 20 categories -- communication, social, databases, DevOps, CRM, AI/ML, AWS infrastructure, and more
  • Dual-use design -- works for traditional Python apps (Django, Flask, FastAPI) and AI agents (function calling, tool use) with zero code changes
  • One-line MCP server -- expose any combination of connectors to Claude Desktop, Cursor, or any MCP client
  • Schema generation -- produces OpenAI, Anthropic, and Gemini function-calling schemas from the same source of truth
  • Type-safe everywhere -- Pydantic V2 models for all inputs and outputs, with full JSON Schema generation
  • Async-first, sync-friendly -- every action has both await kit.aexecute() and kit.execute() paths
  • Circuit breakers -- per-connector failure isolation so one dead API doesn't take down your agent
  • Timeout budgets -- per-action and per-request deadlines with automatic retry on transient failures
  • Dry-run mode -- validate destructive actions without executing them
  • BYOK auth -- bring your own API keys and tokens; no OAuth server required in the library
  • Minimal dependencies -- core requires only pydantic, httpx, and docstring-parser

Workflows

1. Direct Python Usage

Use connectors directly in any Python application.

from toolsconnector.serve import ToolKit

kit = ToolKit(["github"], credentials={"github": "ghp_your_token"})

# List open issues
issues = kit.execute("github_list_issues", {
    "owner": "myorg",
    "repo": "myproject",
    "state": "open",
})

2. MCP Server (One Line)

Expose connectors to Claude Desktop, Cursor, Windsurf, or any MCP client.

from toolsconnector.serve import ToolKit

kit = ToolKit(
    ["gmail", "gcalendar", "notion"],
    credentials={"gmail": "ya29.token", "gcalendar": "ya29.token", "notion": "ntn_key"},
)
kit.serve_mcp()  # stdio transport, ready for Claude Desktop

Or from the command line:

# Stdio (one client per process — Claude Desktop launches it as subprocess)
tc serve mcp gmail gcalendar notion --transport stdio

# Long-lived HTTP daemon — multiple agents share one process
tc serve mcp gmail slack github --transport streamable-http --port 9000

The HTTP transport (streamable-http) accepts many concurrent client sessions on the same port — one daemon serves N agents. Per-tool circuit breakers and timeout budgets apply fairly across all clients. There's no built-in auth on the HTTP transport; put it behind a reverse proxy before exposing it publicly.

3. OpenAI Function Calling

Generate tool schemas and execute tool calls from OpenAI responses.

from openai import OpenAI
from toolsconnector.serve import ToolKit

client = OpenAI()
kit = ToolKit(["gmail", "slack"], credentials={...})

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Summarize my unread emails"}],
    tools=kit.to_openai_tools(),
)

# Execute the tool call the model chose
tool_call = response.choices[0].message.tool_calls[0]
result = kit.execute(tool_call.function.name, tool_call.function.arguments)

4. Anthropic Tool Use

Works the same way with Claude's tool use API.

import anthropic
from toolsconnector.serve import ToolKit

client = anthropic.Anthropic()
kit = ToolKit(["jira", "slack"], credentials={...})

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Create a bug ticket for the login issue"}],
    tools=kit.to_anthropic_tools(),
)

# Execute the tool call
for block in response.content:
    if block.type == "tool_use":
        result = kit.execute(block.name, block.input)

5. Google Gemini

Generate Gemini-compatible function declarations.

from toolsconnector.serve import ToolKit

kit = ToolKit(["gmail"], credentials={...})
declarations = kit.to_gemini_tools()
# Pass to google.generativeai as function_declarations

6. CLI Usage

Manage connectors and execute actions from the terminal.

# List all available connectors
tc list

# List actions for a specific connector
tc gmail actions

# Execute an action
tc gmail list_emails --query "is:unread" --max_results 5

# Export the connector spec
tc gmail spec --format json

7. REST API

Serve connectors as HTTP endpoints with Starlette/ASGI.

from toolsconnector.serve import ToolKit

kit = ToolKit(["stripe", "hubspot"], credentials={...})
app = kit.create_rest_app(prefix="/api/v1")

# Run with uvicorn: uvicorn myapp:app --port 8000
# POST /api/v1/stripe/create_charge {"amount": 5000, "currency": "usd"}

Error Handling

Every connector raises typed exceptions from toolsconnector.errors so your code can branch on the failure mode instead of parsing HTTP status codes:

from toolsconnector.errors import (
    InvalidCredentialsError, TokenExpiredError, PermissionDeniedError,
    NotFoundError, RateLimitError, ValidationError, ServerError,
)

try:
    await kit.aexecute("gmail_send_email", {...})
except TokenExpiredError:
    await refresh_oauth_token()
    # ...retry...
except RateLimitError as e:
    await asyncio.sleep(e.retry_after_seconds)  # parsed from Retry-After header
    # ...retry...
except InvalidCredentialsError:
    prompt_user_to_reauthenticate()
except NotFoundError:
    return None  # 404 — caller decides what "missing" means
except PermissionDeniedError:
    request_additional_oauth_scopes()
except ValidationError:
    # 400 / 422 — your arguments were rejected by the upstream API
    raise
except ServerError:
    # 5xx — upstream is having a bad day; retry-eligible
    pass

All typed errors carry connector, action, upstream_status, and a truncated details["body_preview"] — useful for logs and observability. The full taxonomy lives in src/toolsconnector/errors/ if you want to match more granular cases (e.g. ConflictError for 409).


Supported Connectors

79 connectors, 1,650 actions across 20 categories.

Communication (9)

ConnectorInstall ExtraActions
Gmailgmail66
Slackslack51
Discorddiscord25
Microsoft Outlookoutlook23
Microsoft Teamsteams17
Twiliotwilio20
Telegramtelegram26
WhatsApp Businesswhatsapp_business64
WhatsApp (links/QR)whatsapp7

Project Management (4)

ConnectorInstall ExtraActions
Jirajira28
Asanaasana38
Linearlinear19
Trellotrello25

CRM & Support (6)

ConnectorInstall ExtraActions
HubSpothubspot19
Salesforcesalesforce21
Zendeskzendesk16
Freshdeskfreshdesk23
Intercomintercom16
Odooodoo11

Code Platforms (2)

ConnectorInstall ExtraActions
GitHubgithub37
GitLabgitlab21

Knowledge (2)

ConnectorInstall ExtraActions
Notionnotion24
Confluenceconfluence25

Storage (2)

ConnectorInstall ExtraActions
Google Drivegdrive22
AWS S3s320

Database (5)

ConnectorInstall ExtraActions
Airtableairtable26
Firebase Firestorefirestore17
MongoDB Atlasmongodb16
Redis (Upstash)redis18
Supabasesupabase16

DevOps (5)

ConnectorInstall ExtraActions
Cloudflarecloudflare23
Datadogdatadog22
Docker Hubdockerhub14
PagerDutypagerduty16
Vercelvercel16

Finance (2)

ConnectorInstall ExtraActions
Stripestripe40
Plaidplaid17

Marketing (2)

ConnectorInstall ExtraActions
Mailchimpmailchimp23
SendGridsendgrid20

AI / ML (3)

ConnectorInstall ExtraActions
OpenAIopenai26
Anthropicanthropic14
Pineconepinecone15

Analytics (2)

ConnectorInstall ExtraActions
Mixpanelmixpanel14
Segmentsegment14

Message Queue (2)

ConnectorInstall ExtraActions
AWS SQSsqs16
RabbitMQrabbitmq21

Security (2)

ConnectorInstall ExtraActions
Oktaokta21
Auth0auth027

Productivity (6)

ConnectorInstall ExtraActions
Google Calendargcalendar20
Google Docsgdocs5
Google Sheetsgsheets16
Google Tasksgtasks13
Calendlycalendly20
Figmafigma22

E-Commerce (1)

ConnectorInstall ExtraActions
Shopifyshopify27

Custom (1)

ConnectorInstall ExtraActions
Webhookwebhook12

Architecture

ToolsConnector is structured as four layers, each with a single responsibility:

+------------------------------------------------------------------+
|  Serve Layer       ToolKit, MCP, REST, CLI, Schema Generation    |
+------------------------------------------------------------------+
|  Runtime Engine    BaseConnector, @action, Middleware, Auth       |
+------------------------------------------------------------------+
|  Connectors        Gmail, Slack, GitHub, Stripe, ... (68)        |
+------------------------------------------------------------------+
|  Spec Types        Pydantic V2 models, JSON Schema, Contracts    |
+------------------------------------------------------------------+

Spec -- Pure Pydantic V2 models defining the language-agnostic connector contract. No implementation logic. These drive schema generation, MCP serving, documentation, and code generation.

Runtime -- The execution engine. BaseConnector is the abstract base class. The @action decorator parses type hints and docstrings to generate JSON Schema automatically. Middleware handles retry, rate limiting, auth refresh, and structured logging.

Connectors -- 79 implementations, each following the same pattern: subclass BaseConnector, set metadata, implement @action methods. Most use raw httpx for direct HTTP calls. Google and AWS connectors use official SDKs where protocol complexity justifies it.

Serve -- The ToolKit ties everything together. Configure once with a list of connectors and credentials, then serve as MCP, generate OpenAI/Anthropic/Gemini schemas, expose as REST, or call directly from Python.

Adding a Connector

Every connector follows the same structure:

from toolsconnector.runtime import BaseConnector, action
from toolsconnector.spec.connector import ConnectorCategory, ProtocolType

class MyService(BaseConnector):
    name = "myservice"
    display_name = "My Service"
    category = ConnectorCategory.COMMUNICATION
    protocol = ProtocolType.REST
    base_url = "https://api.myservice.com/v1"

    @action(description="List all items", idempotent=True)
    async def list_items(self, limit: int = 20) -> list[dict]:
        """List items from the service.

        Args:
            limit: Maximum number of items to return.
        """
        resp = await self._request("GET", "/items", params={"limit": limit})
        return resp.json()["items"]

The @action decorator handles everything: it parses the type hints and docstring to generate JSON Schema, creates a sync wrapper, and registers the method for discovery by ToolKit.


Contributing

  1. Fork the repository
  2. Create a connector under src/toolsconnector/connectors/yourservice/
  3. Subclass BaseConnector and implement @action methods
  4. Add types in a types.py module using Pydantic V2 models
  5. Add the install extra to pyproject.toml
  6. Write tests under tests/connectors/yourservice/
  7. Submit a pull request

See the existing connectors (e.g., src/toolsconnector/connectors/slack/) for reference implementations.

Requirements

  • Python 3.9+
  • Core dependencies: pydantic>=2.0, httpx>=0.25, docstring-parser>=0.15
  • Connector-specific dependencies installed via extras (e.g., gmail extra installs google-api-python-client)

License

Apache License 2.0. See LICENSE for details.

Collected info

  • ★ 5 stars
  • ⎇ 3 forks
  • Language: Python
  • Source updated: 9/7/2026

Config for your environment

Replace {MCP_ENDPOINT_URL} with this MCP’s endpoint URL (from its repo or docs above). No API key — you connect directly.

Tool

OS

Config file: ~/.cursor/mcp.json

{
  "mcpServers": {
    "mcp-server": {
      "url": "{MCP_ENDPOINT_URL}"
    }
  }
}

Paste into mcpServers in the config file. Restart Cursor after saving.

If this MCP is also published on mcpchannel.ai, you can subscribe from Browse and use the gateway config there instead.