@backendkit-labs/mcp-connectors 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/gcal/server.ts"],"names":[],"mappings":""}
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const node_crypto_1 = require("node:crypto");
6
+ const zod_1 = require("zod");
7
+ const server_runner_js_1 = require("../shared/server-runner.js");
8
+ let tokenCache = null;
9
+ async function getToken() {
10
+ // Return valid cached token (60 s buffer before expiry)
11
+ if (tokenCache && Date.now() < tokenCache.expiresAt - 60_000) {
12
+ return tokenCache.token;
13
+ }
14
+ const saKeyJson = process.env.GCAL_SERVICE_ACCOUNT_KEY;
15
+ if (saKeyJson) {
16
+ const key = JSON.parse(saKeyJson);
17
+ const token = await exchangeServiceAccountToken(key);
18
+ tokenCache = { token, expiresAt: Date.now() + 3_600_000 };
19
+ return token;
20
+ }
21
+ const staticToken = process.env.GCAL_ACCESS_TOKEN;
22
+ if (staticToken)
23
+ return staticToken;
24
+ throw new Error('Set GCAL_SERVICE_ACCOUNT_KEY (recommended) or GCAL_ACCESS_TOKEN');
25
+ }
26
+ async function exchangeServiceAccountToken(key) {
27
+ const now = Math.floor(Date.now() / 1000);
28
+ const tokenUri = key.token_uri ?? 'https://oauth2.googleapis.com/token';
29
+ const payload = {
30
+ iss: key.client_email,
31
+ scope: 'https://www.googleapis.com/auth/calendar',
32
+ aud: tokenUri,
33
+ exp: now + 3600,
34
+ iat: now,
35
+ };
36
+ const header = Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })).toString('base64url');
37
+ const body = Buffer.from(JSON.stringify(payload)).toString('base64url');
38
+ const toSign = `${header}.${body}`;
39
+ const sign = (0, node_crypto_1.createSign)('RSA-SHA256');
40
+ sign.update(toSign);
41
+ const sig = sign.sign(key.private_key.replace(/\\n/g, '\n'), 'base64url');
42
+ const assertion = `${toSign}.${sig}`;
43
+ const res = await fetch(tokenUri, {
44
+ method: 'POST',
45
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
46
+ body: new URLSearchParams({
47
+ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
48
+ assertion,
49
+ }),
50
+ });
51
+ if (!res.ok) {
52
+ throw new Error(`Service account token exchange failed (${res.status}): ${await res.text()}`);
53
+ }
54
+ const data = await res.json();
55
+ return data.access_token;
56
+ }
57
+ async function gcal(method, path, body) {
58
+ const token = await getToken();
59
+ const url = path.startsWith('http') ? path : `https://www.googleapis.com/calendar/v3${path}`;
60
+ const res = await fetch(url, {
61
+ method,
62
+ headers: {
63
+ 'Authorization': `Bearer ${token}`,
64
+ 'Content-Type': 'application/json',
65
+ },
66
+ body: body !== undefined ? JSON.stringify(body) : undefined,
67
+ });
68
+ if (!res.ok) {
69
+ throw new Error(`Google Calendar ${method} ${path.split('?')[0]} → ${res.status}: ${await res.text()}`);
70
+ }
71
+ return res.json();
72
+ }
73
+ // ── Tools ─────────────────────────────────────────────────────────────────────
74
+ function buildServer() {
75
+ const srv = new mcp_js_1.McpServer({ name: 'bk-mcp-gcal', version: '0.1.0' });
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ const t = srv.tool.bind(srv);
78
+ t('calendar_list_calendars', 'List all Google Calendars accessible to the authenticated account.', {}, async () => {
79
+ const data = await gcal('GET', '/users/me/calendarList');
80
+ const lines = data.items.map(c => `${c.id} "${c.summary}"${c.primary ? ' (primary)' : ''} [${c.accessRole}]`);
81
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
82
+ });
83
+ t('calendar_list_events', 'List upcoming events in a Google Calendar within a time range.', {
84
+ calendar_id: zod_1.z.string().optional().describe('Calendar ID (default: "primary")'),
85
+ time_min: zod_1.z.string().optional().describe('Start of range, ISO 8601 (default: now)'),
86
+ time_max: zod_1.z.string().optional().describe('End of range, ISO 8601 (default: 7 days from now)'),
87
+ limit: zod_1.z.number().optional().describe('Max events (default 10)'),
88
+ }, async ({ calendar_id, time_min, time_max, limit }) => {
89
+ const calId = encodeURIComponent(calendar_id ?? 'primary');
90
+ const tMin = time_min ?? new Date().toISOString();
91
+ const tMax = time_max ?? new Date(Date.now() + 7 * 86_400_000).toISOString();
92
+ const params = new URLSearchParams({
93
+ timeMin: tMin, timeMax: tMax,
94
+ maxResults: String(limit ?? 10),
95
+ singleEvents: 'true', orderBy: 'startTime',
96
+ });
97
+ const data = await gcal('GET', `/calendars/${calId}/events?${params}`);
98
+ const lines = data.items.map(e => {
99
+ const start = e.start.dateTime?.slice(0, 16) ?? e.start.date ?? '?';
100
+ const end = e.end.dateTime?.slice(11, 16) ?? e.end.date ?? '?';
101
+ const attendeeCount = e.attendees?.length ?? 0;
102
+ return `[${start} – ${end}] ${e.summary ?? '(no title)'}${attendeeCount ? ` (${attendeeCount} attendees)` : ''}`;
103
+ });
104
+ return {
105
+ content: [{ type: 'text', text: lines.length ? lines.join('\n') : 'No events found in this range.' }],
106
+ };
107
+ });
108
+ t('calendar_create_event', 'Create a new event in a Google Calendar.', {
109
+ summary: zod_1.z.string().describe('Event title'),
110
+ start: zod_1.z.string().describe('Start time ISO 8601 (e.g. 2026-06-15T10:00:00)'),
111
+ end: zod_1.z.string().describe('End time ISO 8601 (e.g. 2026-06-15T11:00:00)'),
112
+ description: zod_1.z.string().optional().describe('Event description'),
113
+ attendees: zod_1.z.array(zod_1.z.string()).optional().describe('List of attendee email addresses'),
114
+ timezone: zod_1.z.string().optional().describe('IANA timezone (e.g. America/New_York). Default: UTC'),
115
+ calendar_id: zod_1.z.string().optional().describe('Calendar ID (default: "primary")'),
116
+ }, async ({ summary, start, end, description, attendees, timezone, calendar_id }) => {
117
+ const tz = timezone ?? 'UTC';
118
+ const cal = encodeURIComponent(calendar_id ?? 'primary');
119
+ const event = {
120
+ summary,
121
+ start: { dateTime: start, timeZone: tz },
122
+ end: { dateTime: end, timeZone: tz },
123
+ };
124
+ if (description)
125
+ event.description = description;
126
+ if (attendees?.length)
127
+ event.attendees = attendees.map(email => ({ email }));
128
+ const data = await gcal('POST', `/calendars/${cal}/events`, event);
129
+ return {
130
+ content: [{ type: 'text', text: `Event created: ${data.id}\n${data.htmlLink}` }],
131
+ };
132
+ });
133
+ t('calendar_get_freebusy', 'Check the free/busy availability for one or more users in a time range.', {
134
+ emails: zod_1.z.array(zod_1.z.string()).describe('List of email addresses to check'),
135
+ time_min: zod_1.z.string().describe('Start of range, ISO 8601'),
136
+ time_max: zod_1.z.string().describe('End of range, ISO 8601'),
137
+ }, async ({ emails, time_min, time_max }) => {
138
+ const data = await gcal('POST', '/freeBusy', {
139
+ timeMin: time_min, timeMax: time_max,
140
+ items: emails.map(id => ({ id })),
141
+ });
142
+ const lines = emails.map(email => {
143
+ const slots = data.calendars[email]?.busy ?? [];
144
+ if (!slots.length)
145
+ return `${email}: FREE all day`;
146
+ const busyStr = slots.map(s => ` BUSY ${s.start.slice(11, 16)} – ${s.end.slice(11, 16)}`).join('\n');
147
+ return `${email}:\n${busyStr}`;
148
+ });
149
+ return { content: [{ type: 'text', text: lines.join('\n\n') }] };
150
+ });
151
+ return srv;
152
+ }
153
+ // ── Start ─────────────────────────────────────────────────────────────────────
154
+ const { httpMode, port } = (0, server_runner_js_1.parseCliArgs)();
155
+ (0, server_runner_js_1.runMcpServer)(buildServer, { httpMode, port, label: 'bk-mcp-gcal' }).catch(err => {
156
+ process.stderr.write(`[bk-mcp-gcal] Fatal: ${err.message}\n`);
157
+ process.exit(1);
158
+ });
159
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/gcal/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/hubspot/server.ts"],"names":[],"mappings":""}
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const zod_1 = require("zod");
6
+ const server_runner_js_1 = require("../shared/server-runner.js");
7
+ // ── Auth ──────────────────────────────────────────────────────────────────────
8
+ const TOKEN = process.env.HUBSPOT_TOKEN;
9
+ if (!TOKEN) {
10
+ process.stderr.write('[bk-mcp-hubspot] HUBSPOT_TOKEN env var is required (HubSpot Private App token).\n');
11
+ process.exit(1);
12
+ }
13
+ const BASE = 'https://api.hubapi.com';
14
+ async function hs(method, path, body) {
15
+ const res = await fetch(`${BASE}${path}`, {
16
+ method,
17
+ headers: {
18
+ 'Authorization': `Bearer ${TOKEN}`,
19
+ 'Content-Type': 'application/json',
20
+ },
21
+ body: body !== undefined ? JSON.stringify(body) : undefined,
22
+ });
23
+ if (!res.ok) {
24
+ throw new Error(`HubSpot ${method} ${path.split('?')[0]} → ${res.status}: ${await res.text()}`);
25
+ }
26
+ return res.json();
27
+ }
28
+ // ── Tools ─────────────────────────────────────────────────────────────────────
29
+ function buildServer() {
30
+ const srv = new mcp_js_1.McpServer({ name: 'bk-mcp-hubspot', version: '0.1.0' });
31
+ // Cast to any to prevent TypeScript from attempting deep Zod schema inference
32
+ // during declaration emit — the MCP SDK validates schemas at runtime.
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ const t = srv.tool.bind(srv);
35
+ t('crm_search_contacts', 'Search HubSpot CRM contacts by name, email, or company.', {
36
+ query: zod_1.z.string().describe('Search term — name, email, or company'),
37
+ limit: zod_1.z.number().optional().describe('Max results (default 10)'),
38
+ }, async ({ query, limit }) => {
39
+ const data = await hs('POST', '/crm/v3/objects/contacts/search', {
40
+ query,
41
+ limit: limit ?? 10,
42
+ properties: ['firstname', 'lastname', 'email', 'phone', 'company'],
43
+ });
44
+ const lines = data.results.map(c => {
45
+ const p = c.properties;
46
+ return `ID:${c.id} ${p.firstname ?? ''} ${p.lastname ?? ''} <${p.email ?? ''}> ${p.company ?? ''} ${p.phone ?? ''}`.trim();
47
+ });
48
+ return {
49
+ content: [{ type: 'text', text: lines.length ? lines.join('\n') : 'No contacts found.' }],
50
+ };
51
+ });
52
+ t('crm_get_contact', 'Get full property details for a HubSpot contact by ID.', {
53
+ id: zod_1.z.string().describe('HubSpot contact ID'),
54
+ }, async ({ id }) => {
55
+ const props = 'firstname,lastname,email,phone,company,jobtitle,lifecyclestage,createdate,lastmodifieddate';
56
+ const data = await hs('GET', `/crm/v3/objects/contacts/${id}?properties=${props}`);
57
+ const lines = Object.entries(data.properties)
58
+ .filter(([, v]) => v)
59
+ .map(([k, v]) => `${k}: ${v}`);
60
+ return {
61
+ content: [{ type: 'text', text: `Contact ${id}\n${lines.join('\n')}` }],
62
+ };
63
+ });
64
+ t('crm_create_contact', 'Create a new contact in HubSpot CRM.', {
65
+ email: zod_1.z.string().describe('Email address (required)'),
66
+ firstname: zod_1.z.string().optional(),
67
+ lastname: zod_1.z.string().optional(),
68
+ phone: zod_1.z.string().optional(),
69
+ company: zod_1.z.string().optional(),
70
+ jobtitle: zod_1.z.string().optional(),
71
+ }, async (props) => {
72
+ const properties = {};
73
+ for (const [k, v] of Object.entries(props)) {
74
+ if (v)
75
+ properties[k] = v;
76
+ }
77
+ const data = await hs('POST', '/crm/v3/objects/contacts', { properties });
78
+ return { content: [{ type: 'text', text: `Created contact ID: ${data.id}` }] };
79
+ });
80
+ t('crm_search_deals', 'Search HubSpot CRM deals by name and/or deal stage.', {
81
+ query: zod_1.z.string().optional().describe('Deal name search term'),
82
+ stage: zod_1.z.string().optional().describe('Deal stage key (e.g. appointmentscheduled, closedwon)'),
83
+ limit: zod_1.z.number().optional().describe('Max results (default 10)'),
84
+ }, async ({ query, stage, limit }) => {
85
+ const body = {
86
+ limit: limit ?? 10,
87
+ properties: ['dealname', 'dealstage', 'amount', 'closedate'],
88
+ };
89
+ if (query)
90
+ body.query = query;
91
+ if (stage) {
92
+ body.filterGroups = [{
93
+ filters: [{ propertyName: 'dealstage', operator: 'EQ', value: stage }],
94
+ }];
95
+ }
96
+ const data = await hs('POST', '/crm/v3/objects/deals/search', body);
97
+ const lines = data.results.map(d => {
98
+ const p = d.properties;
99
+ return `ID:${d.id} ${p.dealname ?? ''} stage:${p.dealstage ?? ''} $${p.amount ?? '0'} close:${p.closedate?.slice(0, 10) ?? '-'}`;
100
+ });
101
+ return {
102
+ content: [{ type: 'text', text: lines.length ? lines.join('\n') : 'No deals found.' }],
103
+ };
104
+ });
105
+ t('crm_create_note', 'Log an activity note in HubSpot, optionally associated with a contact or deal.', {
106
+ body: zod_1.z.string().describe('Note text content'),
107
+ contact_id: zod_1.z.string().optional().describe('HubSpot contact ID to associate'),
108
+ deal_id: zod_1.z.string().optional().describe('HubSpot deal ID to associate'),
109
+ }, async ({ body, contact_id, deal_id }) => {
110
+ const associations = [];
111
+ if (contact_id) {
112
+ associations.push({ to: { id: contact_id }, types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 202 }] });
113
+ }
114
+ if (deal_id) {
115
+ associations.push({ to: { id: deal_id }, types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 214 }] });
116
+ }
117
+ const data = await hs('POST', '/crm/v3/objects/notes', {
118
+ properties: { hs_note_body: body, hs_timestamp: Date.now().toString() },
119
+ associations,
120
+ });
121
+ return { content: [{ type: 'text', text: `Created note ID: ${data.id}` }] };
122
+ });
123
+ return srv;
124
+ }
125
+ // ── Start ─────────────────────────────────────────────────────────────────────
126
+ const { httpMode, port } = (0, server_runner_js_1.parseCliArgs)();
127
+ (0, server_runner_js_1.runMcpServer)(buildServer, { httpMode, port, label: 'bk-mcp-hubspot' }).catch(err => {
128
+ process.stderr.write(`[bk-mcp-hubspot] Fatal: ${err.message}\n`);
129
+ process.exit(1);
130
+ });
131
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/hubspot/server.ts"],"names":[],"mappings":";;;AACA,oEAAoE;AACpE,6BAAwB;AACxB,iEAAwE;AAExE,iFAAiF;AAEjF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AACxC,IAAI,CAAC,KAAK,EAAE,CAAC;IACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mFAAmF,CAAC,CAAC;IAC1G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAEtC,KAAK,UAAU,EAAE,CAAI,MAAc,EAAE,IAAY,EAAE,IAAc;IAC7D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;QACtC,MAAM;QACN,OAAO,EAAE;YACL,eAAe,EAAE,UAAU,KAAK,EAAE;YAClC,cAAc,EAAE,kBAAkB;SACrC;QACD,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9D,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,WAAW,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AACpC,CAAC;AAED,iFAAiF;AAEjF,SAAS,WAAW;IAChB,MAAM,GAAG,GAAG,IAAI,kBAAS,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACxE,8EAA8E;IAC9E,sEAAsE;IACtE,8DAA8D;IAC9D,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAQ,CAAC;IAEpC,CAAC,CACG,qBAAqB,EACrB,yDAAyD,EACzD;QACI,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;QACnE,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;KACpE,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAqC,EAAE,EAAE;QAC1D,MAAM,IAAI,GAAG,MAAM,EAAE,CAElB,MAAM,EAAE,iCAAiC,EAAE;YAC1C,KAAK;YACL,KAAK,EAAE,KAAK,IAAI,EAAE;YAClB,UAAU,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC;SACrE,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YACvB,OAAO,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,CAAC,CAAC,QAAQ,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,IAAI,EAAE,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;QACnI,CAAC,CAAC,CAAC;QACH,OAAO;YACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,CAAC;SACrG,CAAC;IACN,CAAC,CACJ,CAAC;IAEF,CAAC,CACG,iBAAiB,EACjB,wDAAwD,EACxD;QACI,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;KAChD,EACD,KAAK,EAAE,EAAE,EAAE,EAAkB,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,4FAA4F,CAAC;QAC3G,MAAM,IAAI,GAAG,MAAM,EAAE,CACjB,KAAK,EAAE,4BAA4B,EAAE,eAAe,KAAK,EAAE,CAC9D,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;aACxC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;aACpB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO;YACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;SACnF,CAAC;IACN,CAAC,CACJ,CAAC;IAEF,CAAC,CACG,oBAAoB,EACpB,sCAAsC,EACtC;QACI,KAAK,EAAM,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QAC1D,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,QAAQ,EAAG,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,KAAK,EAAM,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,OAAO,EAAI,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,QAAQ,EAAG,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACnC,EACD,KAAK,EAAE,KAAoH,EAAE,EAAE;QAC3H,MAAM,UAAU,GAA2B,EAAE,CAAC;QAC9C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC;gBAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAiB,MAAM,EAAE,0BAA0B,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1F,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,uBAAuB,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;IAC5F,CAAC,CACJ,CAAC;IAEF,CAAC,CACG,kBAAkB,EAClB,qDAAqD,EACrD;QACI,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAC9D,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;QAC9F,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;KACpE,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAsD,EAAE,EAAE;QAClF,MAAM,IAAI,GAA4B;YAClC,KAAK,EAAE,KAAK,IAAI,EAAE;YAClB,UAAU,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC;SAC/D,CAAC;QACF,IAAI,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAC9B,IAAI,KAAK,EAAE,CAAC;YACR,IAAI,CAAC,YAAY,GAAG,CAAC;oBACjB,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;iBACzE,CAAC,CAAC;QACP,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAElB,MAAM,EAAE,8BAA8B,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YACvB,OAAO,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,IAAI,EAAE,WAAW,CAAC,CAAC,SAAS,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC;QACzI,CAAC,CAAC,CAAC;QACH,OAAO;YACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;SAClG,CAAC;IACN,CAAC,CACJ,CAAC;IAEF,CAAC,CACG,iBAAiB,EACjB,gFAAgF,EAChF;QACI,IAAI,EAAQ,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACpD,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;QAC7E,OAAO,EAAK,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;KAC7E,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAA2D,EAAE,EAAE;QAE7F,MAAM,YAAY,GAAY,EAAE,CAAC;QACjC,IAAI,UAAU,EAAE,CAAC;YACb,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/H,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACV,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5H,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAiB,MAAM,EAAE,uBAAuB,EAAE;YACnE,UAAU,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE;YACvE,YAAY;SACf,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,oBAAoB,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CACJ,CAAC;IAEF,OAAO,GAAG,CAAC;AACf,CAAC;AAED,iFAAiF;AAEjF,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAA,+BAAY,GAAE,CAAC;AAC1C,IAAA,+BAAY,EAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IAC/E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA4B,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;IAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const version = "0.1.0";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.version = void 0;
4
+ // Entry point is unused at runtime — each connector runs as its own binary.
5
+ // This file exists so TypeScript emits a dist/index.js (required by package.json "main").
6
+ exports.version = '0.1.0';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4EAA4E;AAC5E,0FAA0F;AAC7E,QAAA,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/jira/server.ts"],"names":[],"mappings":""}
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const zod_1 = require("zod");
6
+ const server_runner_js_1 = require("../shared/server-runner.js");
7
+ // ── Auth ──────────────────────────────────────────────────────────────────────
8
+ const HOST = process.env.JIRA_HOST; // e.g. mycompany.atlassian.net
9
+ const EMAIL = process.env.JIRA_EMAIL;
10
+ const TOKEN = process.env.JIRA_TOKEN; // Jira API token (not password)
11
+ const missing = [!HOST && 'JIRA_HOST', !EMAIL && 'JIRA_EMAIL', !TOKEN && 'JIRA_TOKEN'].filter(Boolean);
12
+ if (missing.length) {
13
+ process.stderr.write(`[bk-mcp-jira] Missing env vars: ${missing.join(', ')}\n`);
14
+ process.exit(1);
15
+ }
16
+ const BASE = `https://${HOST}/rest/api/3`;
17
+ const AUTH = Buffer.from(`${EMAIL}:${TOKEN}`).toString('base64');
18
+ async function jira(method, path, body) {
19
+ const res = await fetch(`${BASE}${path}`, {
20
+ method,
21
+ headers: {
22
+ 'Authorization': `Basic ${AUTH}`,
23
+ 'Content-Type': 'application/json',
24
+ 'Accept': 'application/json',
25
+ },
26
+ body: body !== undefined ? JSON.stringify(body) : undefined,
27
+ });
28
+ if (res.status === 204)
29
+ return undefined;
30
+ if (!res.ok) {
31
+ throw new Error(`Jira ${method} ${path.split('?')[0]} → ${res.status}: ${await res.text()}`);
32
+ }
33
+ return res.json();
34
+ }
35
+ function adfText(node) {
36
+ if (!node)
37
+ return '';
38
+ if (node.text)
39
+ return node.text;
40
+ if (!node.content)
41
+ return '';
42
+ const sep = node.type === 'paragraph' || node.type === 'doc' ? '\n' : '';
43
+ return node.content.map(adfText).join(sep);
44
+ }
45
+ function adfDoc(text) {
46
+ return {
47
+ type: 'doc', version: 1,
48
+ content: [{ type: 'paragraph', content: [{ type: 'text', text }] }],
49
+ };
50
+ }
51
+ // ── Tools ─────────────────────────────────────────────────────────────────────
52
+ function buildServer() {
53
+ const srv = new mcp_js_1.McpServer({ name: 'bk-mcp-jira', version: '0.1.0' });
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ const t = srv.tool.bind(srv);
56
+ t('jira_search', 'Search Jira issues using JQL (Jira Query Language). Returns key, summary, status, and assignee.', {
57
+ jql: zod_1.z.string().describe('JQL query (e.g. "project=PROJ AND status=\\"In Progress\\"")'),
58
+ limit: zod_1.z.number().optional().describe('Max results (default 20)'),
59
+ }, async ({ jql, limit }) => {
60
+ const data = await jira('GET', `/search?jql=${encodeURIComponent(jql)}&maxResults=${limit ?? 20}&fields=summary,status,assignee,priority`);
61
+ const lines = data.issues.map(i => {
62
+ const f = i.fields;
63
+ return `${i.key} [${f.status.name}] ${f.priority?.name ?? '-'} ${f.summary} @${f.assignee?.displayName ?? 'unassigned'}`;
64
+ });
65
+ return {
66
+ content: [{ type: 'text', text: lines.length ? lines.join('\n') : 'No issues found.' }],
67
+ };
68
+ });
69
+ t('jira_get_issue', 'Get full details for a Jira issue including description and recent comments.', {
70
+ key: zod_1.z.string().describe('Jira issue key (e.g. PROJ-123)'),
71
+ }, async ({ key }) => {
72
+ const data = await jira('GET', `/issue/${key}?fields=summary,status,assignee,description,comment`);
73
+ const f = data.fields;
74
+ const desc = adfText(f.description);
75
+ const comments = f.comment.comments.slice(-3).map(c => ` [${c.author.displayName} · ${c.created.slice(0, 10)}]: ${adfText(c.body)}`);
76
+ const parts = [
77
+ `${key}: ${f.summary}`,
78
+ `Status: ${f.status.name} Assignee: ${f.assignee?.displayName ?? 'unassigned'}`,
79
+ desc ? `\nDescription:\n${desc}` : '',
80
+ comments.length ? `\nComments (last ${comments.length}):\n${comments.join('\n')}` : '',
81
+ ].filter(Boolean);
82
+ return { content: [{ type: 'text', text: parts.join('\n') }] };
83
+ });
84
+ t('jira_create_issue', 'Create a new Jira issue.', {
85
+ project: zod_1.z.string().describe('Project key (e.g. PROJ)'),
86
+ summary: zod_1.z.string().describe('Issue title/summary'),
87
+ description: zod_1.z.string().optional().describe('Issue description (plain text)'),
88
+ issue_type: zod_1.z.string().optional().describe('Issue type (e.g. Task, Bug, Story). Default: Task'),
89
+ priority: zod_1.z.string().optional().describe('Priority (e.g. High, Medium, Low)'),
90
+ }, async ({ project, summary, description, issue_type, priority }) => {
91
+ const fields = {
92
+ project: { key: project },
93
+ summary,
94
+ issuetype: { name: issue_type ?? 'Task' },
95
+ };
96
+ if (description)
97
+ fields.description = adfDoc(description);
98
+ if (priority)
99
+ fields.priority = { name: priority };
100
+ const data = await jira('POST', '/issue', { fields });
101
+ return { content: [{ type: 'text', text: `Created ${data.key} (ID: ${data.id})` }] };
102
+ });
103
+ t('jira_add_comment', 'Add a comment to a Jira issue.', {
104
+ key: zod_1.z.string().describe('Issue key (e.g. PROJ-123)'),
105
+ body: zod_1.z.string().describe('Comment text'),
106
+ }, async ({ key, body }) => {
107
+ await jira('POST', `/issue/${key}/comment`, { body: adfDoc(body) });
108
+ return { content: [{ type: 'text', text: `Comment added to ${key}.` }] };
109
+ });
110
+ t('jira_transition', 'Move a Jira issue to a new status (e.g. "In Progress", "Done").', {
111
+ key: zod_1.z.string().describe('Issue key (e.g. PROJ-123)'),
112
+ status: zod_1.z.string().describe('Target status name (e.g. Done, In Progress, To Do)'),
113
+ }, async ({ key, status }) => {
114
+ const { transitions } = await jira('GET', `/issue/${key}/transitions`);
115
+ const match = transitions.find(t => t.name.toLowerCase() === status.toLowerCase());
116
+ if (!match) {
117
+ const available = transitions.map(t => t.name).join(', ');
118
+ throw new Error(`Status "${status}" not available for ${key}. Options: ${available}`);
119
+ }
120
+ await jira('POST', `/issue/${key}/transitions`, { transition: { id: match.id } });
121
+ return { content: [{ type: 'text', text: `${key} → "${match.name}"` }] };
122
+ });
123
+ return srv;
124
+ }
125
+ // ── Start ─────────────────────────────────────────────────────────────────────
126
+ const { httpMode, port } = (0, server_runner_js_1.parseCliArgs)();
127
+ (0, server_runner_js_1.runMcpServer)(buildServer, { httpMode, port, label: 'bk-mcp-jira' }).catch(err => {
128
+ process.stderr.write(`[bk-mcp-jira] Fatal: ${err.message}\n`);
129
+ process.exit(1);
130
+ });
131
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/jira/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function parseCliArgs(): {
3
+ httpMode: boolean;
4
+ port: number;
5
+ };
6
+ export declare function runMcpServer(buildServer: () => McpServer, opts: {
7
+ httpMode: boolean;
8
+ port: number;
9
+ label: string;
10
+ }): Promise<void>;
11
+ //# sourceMappingURL=server-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-runner.d.ts","sourceRoot":"","sources":["../../src/shared/server-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,wBAAgB,YAAY,IAAI;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAOlE;AAED,wBAAsB,YAAY,CAC9B,WAAW,EAAE,MAAM,SAAS,EAC5B,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACzD,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseCliArgs = parseCliArgs;
4
+ exports.runMcpServer = runMcpServer;
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
7
+ const node_http_1 = require("node:http");
8
+ const node_crypto_1 = require("node:crypto");
9
+ function parseCliArgs() {
10
+ const args = process.argv.slice(2);
11
+ const httpMode = args.includes('--http');
12
+ const portEq = args.find(a => a.startsWith('--port='))?.split('=')[1];
13
+ const portSpace = args[args.indexOf('--port') + 1];
14
+ const port = parseInt(portEq ?? portSpace ?? '3001', 10);
15
+ return { httpMode, port };
16
+ }
17
+ async function runMcpServer(buildServer, opts) {
18
+ if (opts.httpMode) {
19
+ await startHttp(buildServer, opts.port, opts.label);
20
+ }
21
+ else {
22
+ const transport = new stdio_js_1.StdioServerTransport();
23
+ await buildServer().connect(transport);
24
+ }
25
+ }
26
+ async function startHttp(buildServer, port, label) {
27
+ const sessions = new Map();
28
+ const MCP_PATH = '/mcp';
29
+ async function parseBody(req) {
30
+ const chunks = [];
31
+ for await (const chunk of req)
32
+ chunks.push(chunk);
33
+ const raw = Buffer.concat(chunks).toString('utf-8');
34
+ if (!raw)
35
+ return undefined;
36
+ return JSON.parse(raw);
37
+ }
38
+ const httpServer = (0, node_http_1.createServer)(async (req, res) => {
39
+ if (req.url !== MCP_PATH) {
40
+ res.writeHead(404, { 'Content-Type': 'application/json' });
41
+ res.end(JSON.stringify({ error: `Use POST/GET ${MCP_PATH}` }));
42
+ return;
43
+ }
44
+ try {
45
+ const sessionId = req.headers['mcp-session-id'];
46
+ if (sessionId && sessions.has(sessionId)) {
47
+ const body = req.method === 'POST' ? await parseBody(req) : undefined;
48
+ await sessions.get(sessionId).handleRequest(req, res, body);
49
+ return;
50
+ }
51
+ if (req.method !== 'POST') {
52
+ res.writeHead(400);
53
+ res.end('Session ID required for GET');
54
+ return;
55
+ }
56
+ const body = await parseBody(req);
57
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
58
+ sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
59
+ });
60
+ const srv = buildServer();
61
+ await srv.connect(transport);
62
+ await transport.handleRequest(req, res, body);
63
+ if (transport.sessionId) {
64
+ sessions.set(transport.sessionId, transport);
65
+ transport.onclose = () => sessions.delete(transport.sessionId);
66
+ }
67
+ }
68
+ catch (err) {
69
+ if (!res.headersSent) {
70
+ res.writeHead(500);
71
+ res.end(String(err));
72
+ }
73
+ }
74
+ });
75
+ await new Promise((resolve, reject) => {
76
+ httpServer.once('error', reject);
77
+ httpServer.listen(port, '127.0.0.1', () => {
78
+ process.stderr.write(`[${label}] HTTP listening on http://127.0.0.1:${port}${MCP_PATH}\n`);
79
+ resolve();
80
+ });
81
+ });
82
+ }
83
+ //# sourceMappingURL=server-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-runner.js","sourceRoot":"","sources":["../../src/shared/server-runner.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@backendkit-labs/mcp-connectors",
3
+ "version": "0.1.0",
4
+ "description": "Enterprise MCP connectors — HubSpot CRM, Jira, Google Calendar",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "bk-mcp-hubspot": "./dist/hubspot/server.js",
9
+ "bk-mcp-jira": "./dist/jira/server.js",
10
+ "bk-mcp-gcal": "./dist/gcal/server.js"
11
+ },
12
+ "files": ["dist/", "README.md"],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/BackendKit-labs/backendkit-agent-framework.git",
16
+ "directory": "packages/mcp-connectors"
17
+ },
18
+ "publishConfig": { "access": "public" },
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "tsc --watch",
22
+ "typecheck": "tsc --noEmit",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.12.0",
27
+ "zod": "^3.23.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.0.0",
31
+ "typescript": "^5.4.0"
32
+ },
33
+ "engines": { "node": ">=20.0.0" }
34
+ }