{"id":49170025,"url":"https://github.com/sachinshelke/toolsconnector","last_synced_at":"2026-05-01T02:00:39.497Z","repository":{"id":351541232,"uuid":"1201569317","full_name":"sachinshelke/ToolsConnector","owner":"sachinshelke","description":"Open-source Python library for 68 API connectors — Gmail, Slack, GitHub, Stripe, OpenAI, Anthropic \u0026 more. MCP server, OpenAI function calling, Anthropic tool use. 1,370+ actions. Apache 2.0.","archived":false,"fork":false,"pushed_at":"2026-05-01T01:05:06.000Z","size":2636,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-01T01:17:44.561Z","etag":null,"topics":["ai-agents","anthropic-tool-use","api-connector","langchain","llm-tools","mcp-server","open-source","openai-function-calling","python","tool-use"],"latest_commit_sha":null,"homepage":"https://toolsconnector.github.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sachinshelke.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":".github/SUPPORT.md","governance":"GOVERNANCE.md","roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-04T21:19:36.000Z","updated_at":"2026-05-01T01:05:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"aacc6f86-2630-43cb-88f4-1b03cfdf4497","html_url":"https://github.com/sachinshelke/ToolsConnector","commit_stats":null,"previous_names":["sachinshelke/toolsconnector"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/sachinshelke/ToolsConnector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinshelke%2FToolsConnector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinshelke%2FToolsConnector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinshelke%2FToolsConnector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinshelke%2FToolsConnector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sachinshelke","download_url":"https://codeload.github.com/sachinshelke/ToolsConnector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinshelke%2FToolsConnector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32482460,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","anthropic-tool-use","api-connector","langchain","llm-tools","mcp-server","open-source","openai-function-calling","python","tool-use"],"created_at":"2026-04-22T18:00:39.092Z","updated_at":"2026-05-01T02:00:39.490Z","avatar_url":"https://github.com/sachinshelke.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ToolsConnector\n\n**One interface, every tool. Connect 68+ APIs to your Python app or AI agent in minutes.**\n\n[![PyPI version](https://img.shields.io/pypi/v/toolsconnector.svg?color=blue)](https://pypi.org/project/toolsconnector/)\n[![Python 3.9+](https://img.shields.io/pypi/pyversions/toolsconnector.svg)](https://pypi.org/project/toolsconnector/)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![CI](https://github.com/sachinshelke/ToolsConnector/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/sachinshelke/ToolsConnector/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/sachinshelke/ToolsConnector/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/sachinshelke/ToolsConnector/security/code-scanning)\n[![Pydantic V2](https://img.shields.io/badge/pydantic-v2-e92063.svg)](https://docs.pydantic.dev/)\n[![PyPI downloads](https://img.shields.io/pypi/dm/toolsconnector.svg?color=brightgreen)](https://pypi.org/project/toolsconnector/)\n[![Typed](https://img.shields.io/badge/typing-typed-blue.svg)](https://peps.python.org/pep-0561/)\n\n---\n\n## The Problem\n\nEvery 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.\n\nToolsConnector gives you a single, typed Python interface to **68 connectors and 1,370 actions**. It works identically whether you're building a Django app, an OpenAI agent, or an MCP server for Claude Desktop.\n\n## Run the Documentation Site\n\nTo browse the full connector reference, playground, and guides locally:\n\n```bash\npython3 -m http.server 5001 --directory site\n```\n\nThen open **http://localhost:5001** in your browser.\n\n---\n\n## Install\n\n```bash\npip install toolsconnector\n```\n\nInstall only the connectors you need:\n\n```bash\npip install \"toolsconnector[gmail,slack,github]\"\n```\n\nOr install a full category:\n\n```bash\npip install \"toolsconnector[communication,databases,mcp]\"\n```\n\n## Quick Start\n\n```python\nfrom toolsconnector.serve import ToolKit\n\nkit = ToolKit(\n    [\"gmail\", \"slack\"],\n    credentials={\"gmail\": \"ya29.access-token\", \"slack\": \"xoxb-bot-token\"},\n)\n\n# List unread emails\nresult = kit.execute(\"gmail_list_emails\", {\"query\": \"is:unread\", \"max_results\": 5})\n\n# Send a Slack message\nkit.execute(\"slack_send_message\", {\"channel\": \"#general\", \"text\": \"Deployed v2.1\"})\n```\n\nThat's it. Same `ToolKit`, same `.execute()`, every connector.\n\n## Try the Examples\n\nWant to see real integrations end-to-end? **[`examples/`](examples/)** has 10 copy-pasteable scripts covering every major usage pattern. Pick one closest to what you want to build:\n\n| Pattern | Script |\n|---|---|\n| 5-minute intro: ToolKit + execute | [`01_basic_usage.py`](examples/01_basic_usage.py) |\n| One-line MCP server for Claude Desktop / Cursor | [`02_mcp_server.py`](examples/02_mcp_server.py) |\n| OpenAI function-calling agent (full tool-use loop) | [`03_openai_function_calling.py`](examples/03_openai_function_calling.py) |\n| Anthropic Claude tool-use agent | [`04_anthropic_tool_use.py`](examples/04_anthropic_tool_use.py) |\n| Multi-connector agent with safety filtering | [`05_multi_connector.py`](examples/05_multi_connector.py) |\n| `tc` CLI walkthrough | [`06_cli_usage.sh`](examples/06_cli_usage.sh) |\n| Multi-tenant ToolKitFactory (per-user isolation) | [`07_multi_tenant.py`](examples/07_multi_tenant.py) |\n| Expose connectors as REST API (Starlette + uvicorn) | [`08_rest_api.py`](examples/08_rest_api.py) |\n| CI health checks, spec extraction, OpenAPI export | [`09_health_check.py`](examples/09_health_check.py) |\n| Publish to LinkedIn end-to-end | [`10_linkedin_publish.py`](examples/10_linkedin_publish.py) |\n\nSee [`examples/README.md`](examples/README.md) for the full table with required env vars.\n\n---\n\n## Key Features\n\n- **68 connectors, 1,370 actions** across 20 categories -- communication, social, databases, DevOps, CRM, AI/ML, AWS infrastructure, and more\n- **Dual-use design** -- works for traditional Python apps (Django, Flask, FastAPI) and AI agents (function calling, tool use) with zero code changes\n- **One-line MCP server** -- expose any combination of connectors to Claude Desktop, Cursor, or any MCP client\n- **Schema generation** -- produces OpenAI, Anthropic, and Gemini function-calling schemas from the same source of truth\n- **Type-safe everywhere** -- Pydantic V2 models for all inputs and outputs, with full JSON Schema generation\n- **Async-first, sync-friendly** -- every action has both `await kit.aexecute()` and `kit.execute()` paths\n- **Circuit breakers** -- per-connector failure isolation so one dead API doesn't take down your agent\n- **Timeout budgets** -- per-action and per-request deadlines with automatic retry on transient failures\n- **Dry-run mode** -- validate destructive actions without executing them\n- **BYOK auth** -- bring your own API keys and tokens; no OAuth server required in the library\n- **Minimal dependencies** -- core requires only `pydantic`, `httpx`, and `docstring-parser`\n\n---\n\n## Workflows\n\n### 1. Direct Python Usage\n\nUse connectors directly in any Python application.\n\n```python\nfrom toolsconnector.serve import ToolKit\n\nkit = ToolKit([\"github\"], credentials={\"github\": \"ghp_your_token\"})\n\n# List open issues\nissues = kit.execute(\"github_list_issues\", {\n    \"owner\": \"myorg\",\n    \"repo\": \"myproject\",\n    \"state\": \"open\",\n})\n```\n\n### 2. MCP Server (One Line)\n\nExpose connectors to Claude Desktop, Cursor, Windsurf, or any MCP client.\n\n```python\nfrom toolsconnector.serve import ToolKit\n\nkit = ToolKit(\n    [\"gmail\", \"gcalendar\", \"notion\"],\n    credentials={\"gmail\": \"ya29.token\", \"gcalendar\": \"ya29.token\", \"notion\": \"ntn_key\"},\n)\nkit.serve_mcp()  # stdio transport, ready for Claude Desktop\n```\n\nOr from the command line:\n\n```bash\n# Stdio (one client per process — Claude Desktop launches it as subprocess)\ntc serve mcp gmail gcalendar notion --transport stdio\n\n# Long-lived HTTP daemon — multiple agents share one process\ntc serve mcp gmail slack github --transport streamable-http --port 9000\n```\n\nThe HTTP transport (`streamable-http`) accepts many concurrent client\nsessions on the same port — one daemon serves N agents. Per-tool\ncircuit breakers and timeout budgets apply fairly across all clients.\nThere's no built-in auth on the HTTP transport; put it behind a reverse\nproxy before exposing it publicly.\n\n### 3. OpenAI Function Calling\n\nGenerate tool schemas and execute tool calls from OpenAI responses.\n\n```python\nfrom openai import OpenAI\nfrom toolsconnector.serve import ToolKit\n\nclient = OpenAI()\nkit = ToolKit([\"gmail\", \"slack\"], credentials={...})\n\nresponse = client.chat.completions.create(\n    model=\"gpt-4o\",\n    messages=[{\"role\": \"user\", \"content\": \"Summarize my unread emails\"}],\n    tools=kit.to_openai_tools(),\n)\n\n# Execute the tool call the model chose\ntool_call = response.choices[0].message.tool_calls[0]\nresult = kit.execute(tool_call.function.name, tool_call.function.arguments)\n```\n\n### 4. Anthropic Tool Use\n\nWorks the same way with Claude's tool use API.\n\n```python\nimport anthropic\nfrom toolsconnector.serve import ToolKit\n\nclient = anthropic.Anthropic()\nkit = ToolKit([\"jira\", \"slack\"], credentials={...})\n\nresponse = client.messages.create(\n    model=\"claude-sonnet-4-20250514\",\n    max_tokens=1024,\n    messages=[{\"role\": \"user\", \"content\": \"Create a bug ticket for the login issue\"}],\n    tools=kit.to_anthropic_tools(),\n)\n\n# Execute the tool call\nfor block in response.content:\n    if block.type == \"tool_use\":\n        result = kit.execute(block.name, block.input)\n```\n\n### 5. Google Gemini\n\nGenerate Gemini-compatible function declarations.\n\n```python\nfrom toolsconnector.serve import ToolKit\n\nkit = ToolKit([\"gmail\"], credentials={...})\ndeclarations = kit.to_gemini_tools()\n# Pass to google.generativeai as function_declarations\n```\n\n### 6. CLI Usage\n\nManage connectors and execute actions from the terminal.\n\n```bash\n# List all available connectors\ntc list\n\n# List actions for a specific connector\ntc gmail actions\n\n# Execute an action\ntc gmail list_emails --query \"is:unread\" --max_results 5\n\n# Export the connector spec\ntc gmail spec --format json\n```\n\n### 7. REST API\n\nServe connectors as HTTP endpoints with Starlette/ASGI.\n\n```python\nfrom toolsconnector.serve import ToolKit\n\nkit = ToolKit([\"stripe\", \"hubspot\"], credentials={...})\napp = kit.create_rest_app(prefix=\"/api/v1\")\n\n# Run with uvicorn: uvicorn myapp:app --port 8000\n# POST /api/v1/stripe/create_charge {\"amount\": 5000, \"currency\": \"usd\"}\n```\n\n---\n\n## Error Handling\n\nEvery connector raises typed exceptions from `toolsconnector.errors` so\nyour code can branch on the failure mode instead of parsing HTTP status\ncodes:\n\n```python\nfrom toolsconnector.errors import (\n    InvalidCredentialsError, TokenExpiredError, PermissionDeniedError,\n    NotFoundError, RateLimitError, ValidationError, ServerError,\n)\n\ntry:\n    await kit.aexecute(\"gmail_send_email\", {...})\nexcept TokenExpiredError:\n    await refresh_oauth_token()\n    # ...retry...\nexcept RateLimitError as e:\n    await asyncio.sleep(e.retry_after_seconds)  # parsed from Retry-After header\n    # ...retry...\nexcept InvalidCredentialsError:\n    prompt_user_to_reauthenticate()\nexcept NotFoundError:\n    return None  # 404 — caller decides what \"missing\" means\nexcept PermissionDeniedError:\n    request_additional_oauth_scopes()\nexcept ValidationError:\n    # 400 / 422 — your arguments were rejected by the upstream API\n    raise\nexcept ServerError:\n    # 5xx — upstream is having a bad day; retry-eligible\n    pass\n```\n\nAll typed errors carry `connector`, `action`, `upstream_status`, and a\ntruncated `details[\"body_preview\"]` — useful for logs and observability.\nThe full taxonomy lives in `src/toolsconnector/errors/` if you want to\nmatch more granular cases (e.g. `ConflictError` for 409).\n\n---\n\n## Supported Connectors\n\n68 connectors, 1,370 actions across 20 categories.\n\n### Communication (7)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Gmail | `gmail` | 38 |\n| Slack | `slack` | 51 |\n| Discord | `discord` | 25 |\n| Microsoft Outlook | `outlook` | 23 |\n| Microsoft Teams | `teams` | 17 |\n| Twilio | `twilio` | 20 |\n| Telegram | `telegram` | 26 |\n\n### Project Management (4)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Jira | `jira` | 28 |\n| Asana | `asana` | 38 |\n| Linear | `linear` | 19 |\n| Trello | `trello` | 25 |\n\n### CRM \u0026 Support (5)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| HubSpot | `hubspot` | 19 |\n| Salesforce | `salesforce` | 21 |\n| Zendesk | `zendesk` | 16 |\n| Freshdesk | `freshdesk` | 23 |\n| Intercom | `intercom` | 16 |\n\n### Code Platforms (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| GitHub | `github` | 37 |\n| GitLab | `gitlab` | 21 |\n\n### Knowledge (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Notion | `notion` | 20 |\n| Confluence | `confluence` | 25 |\n\n### Storage (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Google Drive | `gdrive` | 22 |\n| AWS S3 | `s3` | 20 |\n\n### Database (5)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Airtable | `airtable` | 26 |\n| Firebase Firestore | `firestore` | 17 |\n| MongoDB Atlas | `mongodb` | 16 |\n| Redis (Upstash) | `redis` | 18 |\n| Supabase | `supabase` | 16 |\n\n### DevOps (5)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Cloudflare | `cloudflare` | 23 |\n| Datadog | `datadog` | 22 |\n| Docker Hub | `dockerhub` | 14 |\n| PagerDuty | `pagerduty` | 16 |\n| Vercel | `vercel` | 16 |\n\n### Finance (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Stripe | `stripe` | 40 |\n| Plaid | `plaid` | 17 |\n\n### Marketing (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Mailchimp | `mailchimp` | 23 |\n| SendGrid | `sendgrid` | 20 |\n\n### AI / ML (3)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| OpenAI | `openai` | 26 |\n| Anthropic | `anthropic` | 14 |\n| Pinecone | `pinecone` | 15 |\n\n### Analytics (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Mixpanel | `mixpanel` | 14 |\n| Segment | `segment` | 14 |\n\n### Message Queue (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| AWS SQS | `sqs` | 16 |\n| RabbitMQ | `rabbitmq` | 21 |\n\n### Security (2)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Okta | `okta` | 21 |\n| Auth0 | `auth0` | 27 |\n\n### Productivity (6)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Google Calendar | `gcalendar` | 20 |\n| Google Docs | `gdocs` | 5 |\n| Google Sheets | `gsheets` | 16 |\n| Google Tasks | `gtasks` | 13 |\n| Calendly | `calendly` | 20 |\n| Figma | `figma` | 22 |\n\n### E-Commerce (1)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Shopify | `shopify` | 27 |\n\n### Custom (1)\n\n| Connector | Install Extra | Actions |\n|-----------|---------------|---------|\n| Webhook | `webhook` | 12 |\n\n---\n\n## Architecture\n\nToolsConnector is structured as four layers, each with a single responsibility:\n\n```\n+------------------------------------------------------------------+\n|  Serve Layer       ToolKit, MCP, REST, CLI, Schema Generation    |\n+------------------------------------------------------------------+\n|  Runtime Engine    BaseConnector, @action, Middleware, Auth       |\n+------------------------------------------------------------------+\n|  Connectors        Gmail, Slack, GitHub, Stripe, ... (68)        |\n+------------------------------------------------------------------+\n|  Spec Types        Pydantic V2 models, JSON Schema, Contracts    |\n+------------------------------------------------------------------+\n```\n\n**Spec** -- Pure Pydantic V2 models defining the language-agnostic connector contract. No implementation logic. These drive schema generation, MCP serving, documentation, and code generation.\n\n**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.\n\n**Connectors** -- 68 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.\n\n**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.\n\n### Adding a Connector\n\nEvery connector follows the same structure:\n\n```python\nfrom toolsconnector.runtime import BaseConnector, action\nfrom toolsconnector.spec.connector import ConnectorCategory, ProtocolType\n\nclass MyService(BaseConnector):\n    name = \"myservice\"\n    display_name = \"My Service\"\n    category = ConnectorCategory.COMMUNICATION\n    protocol = ProtocolType.REST\n    base_url = \"https://api.myservice.com/v1\"\n\n    @action(description=\"List all items\", idempotent=True)\n    async def list_items(self, limit: int = 20) -\u003e list[dict]:\n        \"\"\"List items from the service.\n\n        Args:\n            limit: Maximum number of items to return.\n        \"\"\"\n        resp = await self._request(\"GET\", \"/items\", params={\"limit\": limit})\n        return resp.json()[\"items\"]\n```\n\nThe `@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`.\n\n---\n\n## Contributing\n\n1. Fork the repository\n2. Create a connector under `src/toolsconnector/connectors/yourservice/`\n3. Subclass `BaseConnector` and implement `@action` methods\n4. Add types in a `types.py` module using Pydantic V2 models\n5. Add the install extra to `pyproject.toml`\n6. Write tests under `tests/connectors/yourservice/`\n7. Submit a pull request\n\nSee the existing connectors (e.g., `src/toolsconnector/connectors/slack/`) for reference implementations.\n\n## Requirements\n\n- Python 3.9+\n- Core dependencies: `pydantic\u003e=2.0`, `httpx\u003e=0.25`, `docstring-parser\u003e=0.15`\n- Connector-specific dependencies installed via extras (e.g., `gmail` extra installs `google-api-python-client`)\n\n## License\n\nApache License 2.0. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsachinshelke%2Ftoolsconnector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsachinshelke%2Ftoolsconnector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsachinshelke%2Ftoolsconnector/lists"}