@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.
- package/dist/gcal/server.d.ts +3 -0
- package/dist/gcal/server.d.ts.map +1 -0
- package/dist/gcal/server.js +159 -0
- package/dist/gcal/server.js.map +1 -0
- package/dist/hubspot/server.d.ts +3 -0
- package/dist/hubspot/server.d.ts.map +1 -0
- package/dist/hubspot/server.js +131 -0
- package/dist/hubspot/server.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/jira/server.d.ts +3 -0
- package/dist/jira/server.d.ts.map +1 -0
- package/dist/jira/server.js +131 -0
- package/dist/jira/server.js.map +1 -0
- package/dist/shared/server-runner.d.ts +11 -0
- package/dist/shared/server-runner.d.ts.map +1 -0
- package/dist/shared/server-runner.js +83 -0
- package/dist/shared/server-runner.js.map +1 -0
- package/package.json +34 -0
|
@@ -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 @@
|
|
|
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":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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
|
+
}
|