{"_id":"@backendkit-labs/mcp-connectors","_rev":"3-c2ad36beb41dd42b564442ca331092f0","name":"@backendkit-labs/mcp-connectors","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@backendkit-labs/mcp-connectors","version":"0.1.0","_id":"@backendkit-labs/mcp-connectors@0.1.0","maintainers":[{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"}],"homepage":"https://github.com/BackendKit-labs/backendkit-agent-framework#readme","bugs":{"url":"https://github.com/BackendKit-labs/backendkit-agent-framework/issues"},"bin":{"bk-mcp-gcal":"dist/gcal/server.js","bk-mcp-jira":"dist/jira/server.js","bk-mcp-hubspot":"dist/hubspot/server.js"},"dist":{"shasum":"411ff5945bbf93f74a93e9c4765202c6318eb571","tarball":"https://registry.npmjs.org/@backendkit-labs/mcp-connectors/-/mcp-connectors-0.1.0.tgz","fileCount":21,"integrity":"sha512-zFiFtRwPh2qjUsKaI3ZlwD7YPmmVSF6bMX8mgMr7OFBm9z7ucDi/dEiXBNYI7UQZUOMZ0H3IJ60HGq97vhfXag==","signatures":[{"sig":"MEQCIFL5euvgz81h7urlANx4SfGHJW+Ebnq+zfeCAHHzvgneAiBTcFuZhbxEVv4cWZs7SxtuveTk+UpApuPxRe7go0MO7w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52696},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=20.0.0"},"gitHead":"024826ea1692c5e20adc6f012891a7f06118467f","scripts":{"dev":"tsc --watch","build":"tsc","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"},"repository":{"url":"git+https://github.com/BackendKit-labs/backendkit-agent-framework.git","type":"git","directory":"packages/mcp-connectors"},"_npmVersion":"11.8.0","description":"Enterprise MCP connectors — HubSpot CRM, Jira, Google Calendar","directories":{},"_nodeVersion":"24.16.0","dependencies":{"zod":"^3.23.0","@modelcontextprotocol/sdk":"^1.12.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.4.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-connectors_0.1.0_1781188117667_0.4401243243394617","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@backendkit-labs/mcp-connectors","version":"0.1.1","_id":"@backendkit-labs/mcp-connectors@0.1.1","maintainers":[{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"}],"homepage":"https://github.com/BackendKit-labs/backendkit-agent-framework#readme","bugs":{"url":"https://github.com/BackendKit-labs/backendkit-agent-framework/issues"},"bin":{"bk-mcp-gcal":"dist/gcal/server.js","bk-mcp-jira":"dist/jira/server.js","bk-mcp-hubspot":"dist/hubspot/server.js"},"dist":{"shasum":"ec0843c389e6f36b7b7e33ccc8cdc14ae9a4e5dd","tarball":"https://registry.npmjs.org/@backendkit-labs/mcp-connectors/-/mcp-connectors-0.1.1.tgz","fileCount":22,"integrity":"sha512-evTcFI2srnInFiUG5NHc1UN2AoEMvbet7YWrk836Buv50E1tc9QIHPEFC/DocGDQgG8u4StygFQuPpm9PhYngg==","signatures":[{"sig":"MEYCIQDkk58oONTkW8q/K+qsdPbtsBQxkLxMiUZzt8NFB4QsGwIhAJSnzdZfnOBVQJ35BGJCdzTSSp0JnuBvLxDFXlOgpYJF","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":72969},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=20.0.0"},"gitHead":"7d0711bddc5202b123c766c6651bb923c3aa35e6","scripts":{"dev":"tsc --watch","build":"tsc","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"},"repository":{"url":"git+https://github.com/BackendKit-labs/backendkit-agent-framework.git","type":"git","directory":"packages/mcp-connectors"},"_npmVersion":"11.8.0","description":"Enterprise MCP connectors — HubSpot CRM, Jira, Google Calendar","directories":{},"_nodeVersion":"24.16.0","dependencies":{"zod":"^3.23.0","@modelcontextprotocol/sdk":"^1.12.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.4.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mcp-connectors_0.1.1_1781193370860_0.5007805202628945","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@backendkit-labs/mcp-connectors","version":"0.1.2","description":"Enterprise MCP connectors — HubSpot CRM, Jira, Google Calendar, Odoo ERP","main":"dist/index.js","types":"dist/index.d.ts","bin":{"bk-mcp-hubspot":"dist/hubspot/server.js","bk-mcp-jira":"dist/jira/server.js","bk-mcp-gcal":"dist/gcal/server.js","bk-mcp-odoo":"dist/odoo/server.js"},"repository":{"type":"git","url":"git+https://github.com/BackendKit-labs/backendkit-agent-framework.git","directory":"packages/mcp-connectors"},"publishConfig":{"access":"public"},"scripts":{"build":"tsc","dev":"tsc --watch","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@modelcontextprotocol/sdk":"^1.12.0","zod":"^3.23.0"},"devDependencies":{"@types/node":"^20.0.0","typescript":"^5.4.0"},"engines":{"node":">=20.0.0"},"gitHead":"dc0675448f7f22bfd683588046283860fdfd532d","_id":"@backendkit-labs/mcp-connectors@0.1.2","bugs":{"url":"https://github.com/BackendKit-labs/backendkit-agent-framework/issues"},"homepage":"https://github.com/BackendKit-labs/backendkit-agent-framework#readme","_nodeVersion":"24.16.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-L2LtF+S1OrfDoFl3o7EbM8E8Oy7hdIdahejLydbvADWRTJVIe0n0QKlVD22oJ/pNx9v2MLbeDQWD7Fzc9mV0Fw==","shasum":"68c0d8c8f3a940ca0cda7abdf6913d40f466cbaa","tarball":"https://registry.npmjs.org/@backendkit-labs/mcp-connectors/-/mcp-connectors-0.1.2.tgz","fileCount":26,"unpackedSize":86652,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCy//7QF5v/11j5Xe8Ju5LxaBJlzehtnjPloO/3D/CoDAIgWdE/yEwbgm0csi9lpcgBVfaVuohl9YJnrgbYYAuSyC0="}]},"_npmUser":{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"},"directories":{},"maintainers":[{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-connectors_0.1.2_1781214887179_0.3189543250248452"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-11T14:28:37.495Z","modified":"2026-06-11T21:54:47.451Z","0.1.0":"2026-06-11T14:28:37.852Z","0.1.1":"2026-06-11T15:56:11.013Z","0.1.2":"2026-06-11T21:54:47.324Z"},"bugs":{"url":"https://github.com/BackendKit-labs/backendkit-agent-framework/issues"},"homepage":"https://github.com/BackendKit-labs/backendkit-agent-framework#readme","repository":{"type":"git","url":"git+https://github.com/BackendKit-labs/backendkit-agent-framework.git","directory":"packages/mcp-connectors"},"description":"Enterprise MCP connectors — HubSpot CRM, Jira, Google Calendar, Odoo ERP","maintainers":[{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"}],"readme":"# @backendkit-labs/mcp-connectors\n\n> **Status: `stable`** — Maintained and production-ready. No new features during the pilot phase.\n\nThree production-ready MCP (Model Context Protocol) servers that expose enterprise SaaS integrations as agent tools: **HubSpot CRM**, **Jira**, and **Google Calendar**.\n\nEach connector ships as a standalone binary that runs in stdio mode (for use with any MCP client) or HTTP mode (for multi-tenant server deployments).\n\n[![npm](https://img.shields.io/npm/v/@backendkit-labs/mcp-connectors)](https://www.npmjs.com/package/@backendkit-labs/mcp-connectors)\n\n## Table of contents\n\n- [Installation](#installation)\n- [Running the servers](#running-the-servers)\n- [HubSpot CRM connector](#hubspot-crm-connector)\n- [Jira connector](#jira-connector)\n- [Google Calendar connector](#google-calendar-connector)\n- [Using with agent-core MCPClientManager](#using-with-agent-core-mcpclientmanager)\n- [HTTP mode (multi-session)](#http-mode-multi-session)\n- [Wiring all three connectors](#wiring-all-three-connectors)\n\n---\n\n## Installation\n\n```bash\nnpm install @backendkit-labs/mcp-connectors\n```\n\nThe package ships three binaries:\n\n| Binary | MCP server name |\n|--------|----------------|\n| `bk-mcp-hubspot` | `bk-mcp-hubspot` |\n| `bk-mcp-jira` | `bk-mcp-jira` |\n| `bk-mcp-gcal` | `bk-mcp-gcal` |\n\nOr use via `npx` without installing:\n\n```bash\nnpx @backendkit-labs/mcp-connectors bk-mcp-hubspot\n```\n\n---\n\n## Running the servers\n\n### Stdio mode (default — for MCP clients like Claude Desktop, agent-core)\n\n```bash\n# HubSpot\nHUBSPOT_TOKEN=pat-xxx bk-mcp-hubspot\n\n# Jira\nJIRA_HOST=mycompany.atlassian.net JIRA_EMAIL=me@co.com JIRA_TOKEN=xxx bk-mcp-jira\n\n# Google Calendar (service account — recommended)\nGCAL_SERVICE_ACCOUNT_KEY='{ \"client_email\": \"...\", \"private_key\": \"...\" }' bk-mcp-gcal\n\n# Google Calendar (access token — short-lived, for quick testing)\nGCAL_ACCESS_TOKEN=ya29.xxx bk-mcp-gcal\n```\n\n### HTTP mode (for remote/multi-session deployments)\n\n```bash\nbk-mcp-hubspot --http --port 4001\nbk-mcp-jira    --http --port 4002\nbk-mcp-gcal    --http --port 4003\n```\n\n---\n\n## HubSpot CRM connector\n\n### Authentication\n\nCreate a **Private App** in your HubSpot account (`Settings → Integrations → Private Apps`), grant it the required CRM scopes, and copy the access token:\n\n| Environment variable | Required | Description |\n|---------------------|----------|-------------|\n| `HUBSPOT_TOKEN` | Yes | Private App access token |\n\n### Tools\n\n#### `crm_search_contacts`\n\nSearch contacts by name, email, or company name.\n\n```\nTool: crm_search_contacts\nArgs:\n  query  string   Search term — name, email, or company\n  limit  number?  Max results (default 10)\n```\n\n**Example:**\n```\nsearch for alice@acme.com\n→ crm_search_contacts({ query: \"alice@acme.com\" })\n→ \"ID:12345  Alice Johnson  <alice@acme.com>  Acme Corp  +1-555-0100\"\n```\n\n**Complex example — search and enrich:**\n```\nFind all contacts at Acme Corp and tell me their job titles and when they were created\n→ crm_search_contacts({ query: \"Acme Corp\", limit: 50 })\n→ For each contact: crm_get_contact({ id: \"...\" })\n→ LLM synthesizes a table of names, titles, and creation dates\n```\n\n---\n\n#### `crm_get_contact`\n\nGet full property details for a contact by HubSpot ID.\n\n```\nTool: crm_get_contact\nArgs:\n  id  string  HubSpot contact ID\n```\n\n**Returns:** `firstname`, `lastname`, `email`, `phone`, `company`, `jobtitle`, `lifecyclestage`, `createdate`, `lastmodifieddate`\n\n**Example:**\n```\nGet the full details for contact 12345\n→ crm_get_contact({ id: \"12345\" })\n→ \"Contact 12345\n   firstname: Alice\n   lastname: Johnson\n   email: alice@acme.com\n   jobtitle: VP Engineering\n   lifecyclestage: customer\"\n```\n\n---\n\n#### `crm_create_contact`\n\nCreate a new contact in HubSpot CRM.\n\n```\nTool: crm_create_contact\nArgs:\n  email     string   Email address (required)\n  firstname string?\n  lastname  string?\n  phone     string?\n  company   string?\n  jobtitle  string?\n```\n\n**Example:**\n```\nAdd Bob Smith from Globex as a new CRM contact — bob@globex.com, +1-555-9999, Sr. Engineer\n→ crm_create_contact({\n    email:     \"bob@globex.com\",\n    firstname: \"Bob\",\n    lastname:  \"Smith\",\n    company:   \"Globex\",\n    phone:     \"+1-555-9999\",\n    jobtitle:  \"Sr. Engineer\"\n  })\n→ \"Created contact ID: 67890\"\n```\n\n---\n\n#### `crm_search_deals`\n\nSearch deals by name and/or deal stage.\n\n```\nTool: crm_search_deals\nArgs:\n  query  string?  Deal name search term\n  stage  string?  Deal stage key (e.g. appointmentscheduled, qualifiedtobuy, closedwon, closedlost)\n  limit  number?  Max results (default 10)\n```\n\n**Example — find open deals:**\n```\nShow me all deals in the \"Qualified to Buy\" stage worth over $50k\n→ crm_search_deals({ stage: \"qualifiedtobuy\", limit: 50 })\n→ LLM filters by amount from results\n→ \"ID:111  Enterprise License  stage:qualifiedtobuy  $75,000  close:2026-09-01\"\n```\n\n**Example — search by name:**\n```\nFind the Acme Corp deal\n→ crm_search_deals({ query: \"Acme Corp\" })\n→ \"ID:222  Acme Corp Enterprise  stage:presentationscheduled  $120,000  close:2026-07-15\"\n```\n\n---\n\n#### `crm_create_note`\n\nLog an activity note, optionally linked to a contact and/or deal.\n\n```\nTool: crm_create_note\nArgs:\n  body        string   Note content\n  contact_id  string?  HubSpot contact ID to associate\n  deal_id     string?  HubSpot deal ID to associate\n```\n\n**Example:**\n```\nLog a call note: \"Spoke with Alice, agreed to send proposal by Friday\"\nAssociate with contact 12345 and deal 222\n→ crm_create_note({\n    body:       \"Spoke with Alice, agreed to send proposal by Friday\",\n    contact_id: \"12345\",\n    deal_id:    \"222\"\n  })\n→ \"Created note ID: 333\"\n```\n\n**Complex workflow example:**\n\n```\nAfter our sales call with Acme Corp today:\n1. Find the Acme contact and deal\n2. Log a note about the meeting outcome\n3. Check if the deal close date needs updating\n\n→ crm_search_contacts({ query: \"Alice Acme Corp\" })     → contact 12345\n→ crm_search_deals({ query: \"Acme Corp\" })               → deal 222\n→ crm_create_note({ body: \"...\", contact_id: \"12345\", deal_id: \"222\" })\n→ LLM: \"Note logged. The deal close date is 2026-07-15 — would you like to update it?\"\n```\n\n---\n\n## Jira connector\n\n### Authentication\n\nGenerate an **API token** at `https://id.atlassian.com/manage-profile/security/api-tokens`.\n\n| Environment variable | Required | Description |\n|---------------------|----------|-------------|\n| `JIRA_HOST` | Yes | Your Jira domain (e.g. `mycompany.atlassian.net`) |\n| `JIRA_EMAIL` | Yes | Your Atlassian account email |\n| `JIRA_TOKEN` | Yes | Jira API token (not your password) |\n\n### Tools\n\n#### `jira_search`\n\nSearch Jira issues using JQL (Jira Query Language).\n\n```\nTool: jira_search\nArgs:\n  jql    string   JQL query\n  limit  number?  Max results (default 20)\n```\n\n**JQL examples:**\n```\n# All open bugs in PROJ, assigned to me\njql: project = PROJ AND issuetype = Bug AND status != Done AND assignee = currentUser()\n\n# Recently updated critical issues\njql: priority = Critical AND updated >= -7d ORDER BY updated DESC\n\n# Issues in the current sprint\njql: project = PROJ AND sprint in openSprints()\n\n# My unresolved tasks due this week\njql: assignee = currentUser() AND resolution = Unresolved AND due <= endOfWeek()\n```\n\n**Example:**\n```\nShow me all open bugs in the BACKEND project assigned to Alice\n→ jira_search({ jql: 'project = BACKEND AND issuetype = Bug AND status != Done AND assignee = \"Alice Johnson\"' })\n→ \"BACK-45  [In Progress]  High  Auth token expiry bug  @Alice Johnson\n   BACK-51  [To Do]        Medium  Rate limit not enforced  @Alice Johnson\"\n```\n\n---\n\n#### `jira_get_issue`\n\nGet full details for a Jira issue including description and recent comments.\n\n```\nTool: jira_get_issue\nArgs:\n  key  string  Issue key (e.g. PROJ-123)\n```\n\n**Returns:** summary, status, assignee, description (converted from ADF to plain text), last 3 comments.\n\n**Example:**\n```\nWhat's the current status and description of BACK-45?\n→ jira_get_issue({ key: \"BACK-45\" })\n→ \"BACK-45: Auth token expiry bug\n   Status: In Progress   Assignee: Alice Johnson\n   \n   Description:\n   When a token expires during an active session, the server returns 500\n   instead of 401. Reproduction steps: ...\n   \n   Comments (last 2):\n     [Alice Johnson · 2026-06-10]: Traced to TokenValidator.validate()\n     [Bob Smith · 2026-06-11]: PR opened: https://...\"\n```\n\n---\n\n#### `jira_create_issue`\n\nCreate a new Jira issue.\n\n```\nTool: jira_create_issue\nArgs:\n  project      string   Project key (e.g. PROJ)\n  summary      string   Issue title\n  description  string?  Plain text description\n  issue_type   string?  Issue type (default: Task). E.g. Bug, Story, Epic\n  priority     string?  Priority (Highest, High, Medium, Low, Lowest)\n```\n\n**Example:**\n```\nCreate a high-priority bug in BACK: \"Login fails for SAML users with special characters in email\"\n→ jira_create_issue({\n    project:     \"BACK\",\n    summary:     \"Login fails for SAML users with special characters in email\",\n    description: \"Users with + in email address cannot log in via SAML SSO. Affects @company.com+alias emails.\",\n    issue_type:  \"Bug\",\n    priority:    \"High\"\n  })\n→ \"Created BACK-52 (ID: 100023)\"\n```\n\n---\n\n#### `jira_add_comment`\n\nAdd a comment to a Jira issue.\n\n```\nTool: jira_add_comment\nArgs:\n  key   string  Issue key\n  body  string  Comment text\n```\n\n**Example:**\n```\nAdd a comment to BACK-45: \"Fixed in PR #127, ready for review\"\n→ jira_add_comment({ key: \"BACK-45\", body: \"Fixed in PR #127, ready for review\" })\n→ \"Comment added to BACK-45.\"\n```\n\n---\n\n#### `jira_transition`\n\nMove an issue to a new status (e.g. move from \"To Do\" to \"In Progress\").\n\n```\nTool: jira_transition\nArgs:\n  key     string  Issue key\n  status  string  Target status name (e.g. Done, In Progress, To Do, In Review)\n```\n\nThe tool fetches available transitions first and matches by name (case-insensitive). If the target status isn't available, it reports valid options.\n\n**Example:**\n```\nMark BACK-52 as \"In Progress\"\n→ jira_transition({ key: \"BACK-52\", status: \"In Progress\" })\n→ \"BACK-52 → \"In Progress\"\"\n\nMark BACK-45 as done\n→ jira_transition({ key: \"BACK-45\", status: \"Done\" })\n→ \"BACK-45 → \"Done\"\"\n```\n\n**Complex workflow — sprint management:**\n\n```\nClose out the sprint: mark all Done issues as closed, move remaining In Progress issues to next sprint\n\n→ jira_search({ jql: \"sprint in openSprints() AND status = Done\" })\n  For each: jira_transition({ key: \"...\", status: \"Closed\" })\n\n→ jira_search({ jql: \"sprint in openSprints() AND status = 'In Progress'\" })\n  LLM: \"Found 3 in-progress issues: BACK-48, BACK-50, BACK-53. Move them to next sprint? (I need the sprint ID)\"\n```\n\n---\n\n## Google Calendar connector\n\n### Authentication\n\nTwo auth modes are supported, checked in order:\n\n#### Mode 1: Service Account (recommended for production)\n\nCreate a service account in Google Cloud Console, download the JSON key, and share the target calendar with the service account email. Supports automatic token refresh — no manual intervention needed.\n\n```bash\n# Paste the full JSON content of the service account key file\nGCAL_SERVICE_ACCOUNT_KEY='{\"type\":\"service_account\",\"client_email\":\"bk-agent@my-project.iam.gserviceaccount.com\",\"private_key\":\"-----BEGIN RSA PRIVATE KEY-----\\n...\",\"token_uri\":\"https://oauth2.googleapis.com/token\"}'\n```\n\nThe private key can also contain literal `\\n` (as stored in environment variables) — the server handles unescaping automatically.\n\n#### Mode 2: Access Token (quick testing)\n\n```bash\nGCAL_ACCESS_TOKEN=ya29.a0AfH...   # Google OAuth2 access token (expires in ~1h)\n```\n\n| Environment variable | Required | Description |\n|---------------------|----------|-------------|\n| `GCAL_SERVICE_ACCOUNT_KEY` | Recommended | Full JSON content of a service account key |\n| `GCAL_ACCESS_TOKEN` | Alternative | Short-lived OAuth2 token |\n\n### Tools\n\n#### `calendar_list_calendars`\n\nList all Google Calendars accessible to the authenticated account.\n\n```\nTool: calendar_list_calendars\nArgs: (none)\n```\n\n**Example:**\n```\nWhat calendars do I have access to?\n→ calendar_list_calendars()\n→ \"primary@company.com  \"Alice Johnson\" (primary)  [owner]\n   team-eng@group.calendar.google.com  \"Engineering Team\"  [writer]\n   company-holidays@group.calendar.google.com  \"Company Holidays\"  [reader]\"\n```\n\n---\n\n#### `calendar_list_events`\n\nList upcoming events within a time range.\n\n```\nTool: calendar_list_events\nArgs:\n  calendar_id  string?  Calendar ID (default: \"primary\")\n  time_min     string?  Start of range, ISO 8601 (default: now)\n  time_max     string?  End of range, ISO 8601 (default: 7 days from now)\n  limit        number?  Max events (default 10)\n```\n\n**Example — this week:**\n```\nWhat's on my calendar this week?\n→ calendar_list_events({ limit: 20 })\n→ \"[2026-06-11 09:00 – 09:30] Daily Standup\n   [2026-06-11 14:00 – 15:00] Architecture Review  (4 attendees)\n   [2026-06-12 10:00 – 11:00] 1:1 with Bob\n   [2026-06-13 All Day] Company Holiday\"\n```\n\n**Example — specific calendar and range:**\n```\nShow me all Engineering Team events for next month\n→ calendar_list_events({\n    calendar_id: \"team-eng@group.calendar.google.com\",\n    time_min:    \"2026-07-01T00:00:00Z\",\n    time_max:    \"2026-07-31T23:59:59Z\",\n    limit:       50\n  })\n```\n\n---\n\n#### `calendar_create_event`\n\nCreate a new event in Google Calendar.\n\n```\nTool: calendar_create_event\nArgs:\n  summary      string    Event title (required)\n  start        string    Start time ISO 8601 (required)\n  end          string    End time ISO 8601 (required)\n  description  string?   Event description\n  attendees    string[]? List of attendee email addresses\n  timezone     string?   IANA timezone (default: UTC)\n  calendar_id  string?   Calendar ID (default: \"primary\")\n```\n\n**Example — simple meeting:**\n```\nSchedule a 1-hour team sync tomorrow at 2pm Pacific\n→ calendar_create_event({\n    summary:  \"Team Sync\",\n    start:    \"2026-06-12T14:00:00\",\n    end:      \"2026-06-12T15:00:00\",\n    timezone: \"America/Los_Angeles\"\n  })\n→ \"Event created: abc123def\n   https://calendar.google.com/calendar/event?eid=...\"\n```\n\n**Example — meeting with attendees:**\n```\nBook a sprint planning meeting for next Monday 10am-12pm UTC\nInvite: alice@co.com, bob@co.com, carol@co.com\nAdd agenda to description\n→ calendar_create_event({\n    summary:     \"Sprint Planning — Q3 Sprint 2\",\n    start:       \"2026-06-15T10:00:00\",\n    end:         \"2026-06-15T12:00:00\",\n    timezone:    \"UTC\",\n    description: \"Agenda:\\n1. Review previous sprint\\n2. Story point estimation\\n3. Sprint commitment\",\n    attendees:   [\"alice@co.com\", \"bob@co.com\", \"carol@co.com\"]\n  })\n→ \"Event created: xyz789\n   https://calendar.google.com/...\"\n```\n\n---\n\n#### `calendar_get_freebusy`\n\nCheck free/busy availability for one or more users in a time range.\n\n```\nTool: calendar_get_freebusy\nArgs:\n  emails    string[]  List of email addresses to check (required)\n  time_min  string    Start of range, ISO 8601 (required)\n  time_max  string    End of range, ISO 8601 (required)\n```\n\n**Example — find a meeting slot:**\n```\nFind a 1-hour slot when alice@co.com, bob@co.com, and carol@co.com are all free next Tuesday\n→ calendar_get_freebusy({\n    emails:   [\"alice@co.com\", \"bob@co.com\", \"carol@co.com\"],\n    time_min: \"2026-06-16T08:00:00Z\",\n    time_max: \"2026-06-16T18:00:00Z\"\n  })\n→ \"alice@co.com:\n     BUSY 09:00 – 09:30\n     BUSY 11:00 – 12:00\n   bob@co.com: FREE all day\n   carol@co.com:\n     BUSY 10:00 – 11:30\n     BUSY 14:00 – 15:00\"\n→ LLM: \"Everyone is free from 12:00 to 14:00 and from 15:00 to 18:00. Should I book 12:00–13:00?\"\n```\n\n---\n\n## Using with agent-core MCPClientManager\n\n### Stdio mode (local — recommended for development)\n\n```typescript\nimport { MCPClientManager } from '@backendkit-labs/agent-core';\n\nconst mcp = new MCPClientManager();\n\nawait mcp.connectStdio({\n  name:    'hubspot',\n  command: 'bk-mcp-hubspot',\n  args:    [],\n  env:     { HUBSPOT_TOKEN: process.env.HUBSPOT_TOKEN! },\n});\n\nawait mcp.connectStdio({\n  name:    'jira',\n  command: 'bk-mcp-jira',\n  args:    [],\n  env:     {\n    JIRA_HOST:  process.env.JIRA_HOST!,\n    JIRA_EMAIL: process.env.JIRA_EMAIL!,\n    JIRA_TOKEN: process.env.JIRA_TOKEN!,\n  },\n});\n\nawait mcp.connectStdio({\n  name:    'gcal',\n  command: 'bk-mcp-gcal',\n  args:    [],\n  env:     { GCAL_SERVICE_ACCOUNT_KEY: process.env.GCAL_SERVICE_ACCOUNT_KEY! },\n});\n\n// All tools are now available to the engine\nconst tools = mcp.getTools();\n```\n\n### Via engine options (recommended approach)\n\nPass `mcpServers` to `createBaseEngine` or `createCodingEngine` — the engine manages lifecycle, retries, and disconnect detection:\n\n```typescript\nimport { createBaseEngine } from '@backendkit-labs/agent-core';\n\nconst engine = createBaseEngine({\n  ...baseConfig,\n  mcpServers: [\n    {\n      name:    'hubspot',\n      command: 'npx',\n      args:    ['-y', '@backendkit-labs/mcp-connectors/hubspot'],\n      env:     { HUBSPOT_TOKEN: process.env.HUBSPOT_TOKEN! },\n    },\n    {\n      name:    'jira',\n      command: 'npx',\n      args:    ['-y', '@backendkit-labs/mcp-connectors/jira'],\n      env:     {\n        JIRA_HOST:  process.env.JIRA_HOST!,\n        JIRA_EMAIL: process.env.JIRA_EMAIL!,\n        JIRA_TOKEN: process.env.JIRA_TOKEN!,\n      },\n    },\n    {\n      name:    'gcal',\n      command: 'npx',\n      args:    ['-y', '@backendkit-labs/mcp-connectors/gcal'],\n      env:     { GCAL_SERVICE_ACCOUNT_KEY: process.env.GCAL_SERVICE_ACCOUNT_KEY! },\n    },\n  ],\n});\n```\n\n---\n\n## HTTP mode (multi-session)\n\nStart the servers in HTTP mode when you want to share one connector instance across multiple agent sessions (e.g. in a containerized deployment):\n\n```bash\n# Start connectors as HTTP servers\nHUBSPOT_TOKEN=xxx bk-mcp-hubspot --http --port 4001\nJIRA_HOST=co.atlassian.net JIRA_EMAIL=me@co.com JIRA_TOKEN=xxx bk-mcp-jira --http --port 4002\nGCAL_SERVICE_ACCOUNT_KEY='...' bk-mcp-gcal --http --port 4003\n```\n\nConnect via `connectStreamableHTTP`:\n\n```typescript\nawait mcp.connectStreamableHTTP({ name: 'hubspot', baseUrl: 'http://mcp-hubspot:4001' });\nawait mcp.connectStreamableHTTP({ name: 'jira',    baseUrl: 'http://mcp-jira:4002' });\nawait mcp.connectStreamableHTTP({ name: 'gcal',    baseUrl: 'http://mcp-gcal:4003' });\n```\n\nDocker Compose example:\n\n```yaml\nservices:\n  mcp-hubspot:\n    image: node:20\n    command: [\"npx\", \"-y\", \"@backendkit-labs/mcp-connectors\", \"bk-mcp-hubspot\", \"--http\", \"--port\", \"4001\"]\n    environment:\n      HUBSPOT_TOKEN: ${HUBSPOT_TOKEN}\n    ports: [\"4001:4001\"]\n\n  mcp-jira:\n    image: node:20\n    command: [\"npx\", \"-y\", \"@backendkit-labs/mcp-connectors\", \"bk-mcp-jira\", \"--http\", \"--port\", \"4002\"]\n    environment:\n      JIRA_HOST:  ${JIRA_HOST}\n      JIRA_EMAIL: ${JIRA_EMAIL}\n      JIRA_TOKEN: ${JIRA_TOKEN}\n    ports: [\"4002:4002\"]\n\n  mcp-gcal:\n    image: node:20\n    command: [\"npx\", \"-y\", \"@backendkit-labs/mcp-connectors\", \"bk-mcp-gcal\", \"--http\", \"--port\", \"4003\"]\n    environment:\n      GCAL_SERVICE_ACCOUNT_KEY: ${GCAL_SERVICE_ACCOUNT_KEY}\n    ports: [\"4003:4003\"]\n```\n\n---\n\n## Wiring all three connectors\n\nFull example — an agent that can manage CRM contacts, Jira issues, and calendar events together:\n\n```typescript\nimport { createCodingEngine } from '@backendkit-labs/agent-coding';\n\nconst engine = createCodingEngine({\n  providers: {\n    deepseek: { apiKey: process.env.DEEPSEEK_API_KEY! },\n  },\n  defaultProvider: 'deepseek',\n  mcpServers: [\n    {\n      name:    'hubspot',\n      command: 'bk-mcp-hubspot',\n      args:    [],\n      env:     { HUBSPOT_TOKEN: process.env.HUBSPOT_TOKEN! },\n    },\n    {\n      name:    'jira',\n      command: 'bk-mcp-jira',\n      args:    [],\n      env:     {\n        JIRA_HOST:  process.env.JIRA_HOST!,\n        JIRA_EMAIL: process.env.JIRA_EMAIL!,\n        JIRA_TOKEN: process.env.JIRA_TOKEN!,\n      },\n    },\n    {\n      name:    'gcal',\n      command: 'bk-mcp-gcal',\n      args:    [],\n      env:     { GCAL_SERVICE_ACCOUNT_KEY: process.env.GCAL_SERVICE_ACCOUNT_KEY! },\n    },\n  ],\n});\n\n// Multi-tool agent workflow\nawait engine.run(`\n  I just closed the Acme Corp deal. Please:\n  1. Find the Acme Corp deal in HubSpot and log a note: \"Deal closed — contract signed\"\n  2. Create a Jira task in the ONBOARD project: \"Onboard Acme Corp — enterprise tier\"\n  3. Schedule a kickoff meeting for next Wednesday at 2pm ET with alice@acme.com\n`);\n```\n","readmeFilename":"README.md"}