@x0333/bitrix24-mcp-server 2.0.1 → 2.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/README.md +52 -0
- package/index.js +161 -229
- package/package.json +4 -5
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Bitrix24 MCP Server
|
|
2
|
+
|
|
3
|
+
This is a Model Context Protocol (MCP) server that provides tools for interacting with Bitrix24 via incoming webhooks. It allows AI agents (like Manus, Claude Desktop, etc.) to manage tasks, search for groups, and view user profiles.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **get_profile**: Fetch current user profile information.
|
|
8
|
+
- **get_task**: Retrieve detailed information about a specific task by ID.
|
|
9
|
+
- **search_tasks**: Search for tasks by title with sorting and pagination.
|
|
10
|
+
- **get_group**: Get detailed information about a workgroup or project.
|
|
11
|
+
- **search_groups**: Search for workgroups or projects by name.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
You can run this server directly using `npx`:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx -y @x0333/bitrix24-mcp-server
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
The server requires a Bitrix24 incoming webhook URL. You must set the `B24_BASE` environment variable.
|
|
24
|
+
|
|
25
|
+
### Example for Manus / Claude Desktop
|
|
26
|
+
|
|
27
|
+
Add this to your configuration:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"mcpServers": {
|
|
32
|
+
"bitrix24": {
|
|
33
|
+
"command": "npx",
|
|
34
|
+
"args": ["-y", "@x0333/bitrix24-mcp-server"],
|
|
35
|
+
"env": {
|
|
36
|
+
"B24_BASE": "https://your-domain.bitrix24.ru/rest/USER_ID/WEBHOOK_CODE/"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## How to get Webhook URL
|
|
44
|
+
|
|
45
|
+
1. Go to your Bitrix24 portal.
|
|
46
|
+
2. Navigate to **Developer Resources** -> **Other** -> **Inbound Webhook**.
|
|
47
|
+
3. Select the required permissions (Tasks, Social Network, User).
|
|
48
|
+
4. Copy the **URL for REST API call** (it should look like `https://domain.bitrix24.ru/rest/1/abcdef12345/`).
|
|
49
|
+
|
|
50
|
+
## License
|
|
51
|
+
|
|
52
|
+
MIT
|
package/index.js
CHANGED
|
@@ -1,45 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* Each command prints the JSON response from Bitrix24 to stdout so it can be
|
|
11
|
-
* consumed by downstream tools (including AI models) without additional
|
|
12
|
-
* formatting. If the base URL is not provided via the --base option, the
|
|
13
|
-
* environment variable B24_BASE will be used as a fallback. See README for
|
|
14
|
-
* usage examples.
|
|
15
|
-
*/
|
|
16
|
-
|
|
4
|
+
const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const {
|
|
7
|
+
CallToolRequestSchema,
|
|
8
|
+
ListToolsRequestSchema,
|
|
9
|
+
} = require("@modelcontextprotocol/sdk/types.js");
|
|
17
10
|
const axios = require("axios");
|
|
18
|
-
const { Command } = require("commander");
|
|
19
11
|
|
|
20
12
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* @param {string} base The base URL of the Bitrix24 webhook (no trailing slash).
|
|
26
|
-
* @returns {Promise<any>} Resolves with the parsed JSON data from the response.
|
|
13
|
+
* Bitrix24 MCP Server
|
|
14
|
+
*
|
|
15
|
+
* This server implements the Model Context Protocol (MCP) to provide
|
|
16
|
+
* Bitrix24 integration for AI agents.
|
|
27
17
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
|
|
19
|
+
const B24_BASE = process.env.B24_BASE;
|
|
20
|
+
|
|
21
|
+
if (!B24_BASE) {
|
|
22
|
+
console.error("Error: B24_BASE environment variable is not set.");
|
|
23
|
+
console.error("Please set it to your Bitrix24 webhook URL (e.g., https://domain.bitrix24.ru/rest/1/abcde/).");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const server = new Server(
|
|
28
|
+
{
|
|
29
|
+
name: "bitrix24-mcp-server",
|
|
30
|
+
version: "2.1.0",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
capabilities: {
|
|
34
|
+
tools: {},
|
|
35
|
+
},
|
|
34
36
|
}
|
|
35
|
-
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Helper to call Bitrix24 REST API
|
|
41
|
+
*/
|
|
42
|
+
async function callBitrix(method, body) {
|
|
43
|
+
const url = `${B24_BASE.replace(/\/$/, "")}/${method}`;
|
|
36
44
|
try {
|
|
37
45
|
const response = await axios.post(url, body, {
|
|
38
46
|
headers: { "Content-Type": "application/json" },
|
|
39
47
|
});
|
|
40
48
|
return response.data;
|
|
41
49
|
} catch (err) {
|
|
42
|
-
// Rethrow with a human‑readable message
|
|
43
50
|
const msg = err.response
|
|
44
51
|
? `HTTP ${err.response.status}: ${JSON.stringify(err.response.data)}`
|
|
45
52
|
: err.message;
|
|
@@ -48,218 +55,143 @@ async function callBitrix(method, body, base) {
|
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
/**
|
|
51
|
-
*
|
|
52
|
-
* is falsy.
|
|
53
|
-
*
|
|
54
|
-
* @param {string|undefined} value The comma‑separated string.
|
|
58
|
+
* Define available tools
|
|
55
59
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
61
|
+
return {
|
|
62
|
+
tools: [
|
|
63
|
+
{
|
|
64
|
+
name: "get_profile",
|
|
65
|
+
description: "Fetch current user profile information from Bitrix24",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "get_task",
|
|
73
|
+
description: "Retrieve task details by ID from Bitrix24",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: "object",
|
|
76
|
+
properties: {
|
|
77
|
+
id: { type: "number", description: "The unique ID of the task" },
|
|
78
|
+
select: {
|
|
79
|
+
type: "array",
|
|
80
|
+
items: { type: "string" },
|
|
81
|
+
description: "Fields to return (default: ['*'])"
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
required: ["id"],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "search_tasks",
|
|
89
|
+
description: "Search for tasks by title in Bitrix24",
|
|
90
|
+
inputSchema: {
|
|
91
|
+
type: "object",
|
|
92
|
+
properties: {
|
|
93
|
+
title: { type: "string", description: "Substring of the task title to search for" },
|
|
94
|
+
order: { type: "string", description: "Field to sort by (default: 'ID')" },
|
|
95
|
+
dir: { type: "string", enum: ["asc", "desc"], description: "Sort direction (default: 'desc')" },
|
|
96
|
+
start: { type: "number", description: "Pagination offset (default: 0)" },
|
|
97
|
+
},
|
|
98
|
+
required: ["title"],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "search_groups",
|
|
103
|
+
description: "Search for workgroups or projects by name in Bitrix24",
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: "object",
|
|
106
|
+
properties: {
|
|
107
|
+
name: { type: "string", description: "Substring of the group name to search for" },
|
|
108
|
+
start: { type: "number", description: "Pagination offset (default: 0)" },
|
|
109
|
+
},
|
|
110
|
+
required: ["name"],
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "get_group",
|
|
115
|
+
description: "Retrieve detailed information about a workgroup or project by ID",
|
|
116
|
+
inputSchema: {
|
|
117
|
+
type: "object",
|
|
118
|
+
properties: {
|
|
119
|
+
id: { type: "number", description: "The unique ID of the group" },
|
|
120
|
+
},
|
|
121
|
+
required: ["id"],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
};
|
|
126
|
+
});
|
|
63
127
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"CLI for interacting with Bitrix24 via incoming webhook. Provides commands to query profile, tasks, and workgroups."
|
|
70
|
-
)
|
|
71
|
-
.option(
|
|
72
|
-
"--base <base>",
|
|
73
|
-
"Base URL for Bitrix24 webhook (e.g. https://domain.bitrix24.ru/rest/USER_ID/WEBHOOK_CODE). Defaults to environment variable B24_BASE.",
|
|
74
|
-
undefined
|
|
75
|
-
);
|
|
128
|
+
/**
|
|
129
|
+
* Handle tool calls
|
|
130
|
+
*/
|
|
131
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
132
|
+
const { name, arguments: args } = request.params;
|
|
76
133
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const data = await callBitrix("profile", {}, opts.base);
|
|
84
|
-
console.log(JSON.stringify(data, null, 2));
|
|
85
|
-
});
|
|
134
|
+
try {
|
|
135
|
+
switch (name) {
|
|
136
|
+
case "get_profile": {
|
|
137
|
+
const data = await callBitrix("profile", {});
|
|
138
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
139
|
+
}
|
|
86
140
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
.requiredOption("--id <id>", "Task identifier")
|
|
92
|
-
.option(
|
|
93
|
-
"--select <fields>",
|
|
94
|
-
"Comma‑separated list of fields to select (default '*')",
|
|
95
|
-
undefined
|
|
96
|
-
)
|
|
97
|
-
.action(async (options) => {
|
|
98
|
-
const opts = program.opts();
|
|
99
|
-
const taskId = Number(options.id);
|
|
100
|
-
if (isNaN(taskId)) {
|
|
101
|
-
throw new Error("The --id option must be a number");
|
|
141
|
+
case "get_task": {
|
|
142
|
+
const body = { taskId: args.id, select: args.select || ["*"] };
|
|
143
|
+
const data = await callBitrix("tasks.task.get", body);
|
|
144
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
102
145
|
}
|
|
103
|
-
const select = parseList(options.select) || ["*"];
|
|
104
|
-
const body = { taskId, select };
|
|
105
|
-
const data = await callBitrix("tasks.task.get", body, opts.base);
|
|
106
|
-
console.log(JSON.stringify(data, null, 2));
|
|
107
|
-
});
|
|
108
146
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
.option(
|
|
120
|
-
"--order <field>",
|
|
121
|
-
"Field to sort by (default: ID)",
|
|
122
|
-
"ID"
|
|
123
|
-
)
|
|
124
|
-
.option(
|
|
125
|
-
"--dir <direction>",
|
|
126
|
-
"Sort direction: asc or desc (default: desc)",
|
|
127
|
-
"desc"
|
|
128
|
-
)
|
|
129
|
-
.option(
|
|
130
|
-
"--start <offset>",
|
|
131
|
-
"Pagination offset (multiple of 50; default 0)",
|
|
132
|
-
(value) => Number(value),
|
|
133
|
-
0
|
|
134
|
-
)
|
|
135
|
-
.action(async (options) => {
|
|
136
|
-
const opts = program.opts();
|
|
137
|
-
const select =
|
|
138
|
-
parseList(options.select) || [
|
|
139
|
-
"ID",
|
|
140
|
-
"TITLE",
|
|
141
|
-
"STATUS",
|
|
142
|
-
"RESPONSIBLE_ID",
|
|
143
|
-
"GROUP_ID",
|
|
144
|
-
"CREATED_DATE",
|
|
145
|
-
"CHANGED_DATE",
|
|
146
|
-
];
|
|
147
|
-
const order = { [options.order]: options.dir.toUpperCase() };
|
|
148
|
-
const body = {
|
|
149
|
-
order,
|
|
150
|
-
filter: { "%TITLE": options.title },
|
|
151
|
-
select,
|
|
152
|
-
start: options.start,
|
|
153
|
-
};
|
|
154
|
-
const data = await callBitrix("tasks.task.list", body, opts.base);
|
|
155
|
-
console.log(JSON.stringify(data, null, 2));
|
|
156
|
-
});
|
|
147
|
+
case "search_tasks": {
|
|
148
|
+
const body = {
|
|
149
|
+
order: { [args.order || "ID"]: (args.dir || "desc").toUpperCase() },
|
|
150
|
+
filter: { "%TITLE": args.title },
|
|
151
|
+
select: ["ID", "TITLE", "STATUS", "RESPONSIBLE_ID", "GROUP_ID"],
|
|
152
|
+
start: args.start || 0,
|
|
153
|
+
};
|
|
154
|
+
const data = await callBitrix("tasks.task.list", body);
|
|
155
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
156
|
+
}
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
)
|
|
168
|
-
.option(
|
|
169
|
-
"--order <field>",
|
|
170
|
-
"Field to sort by (default: ID)",
|
|
171
|
-
"ID"
|
|
172
|
-
)
|
|
173
|
-
.option(
|
|
174
|
-
"--dir <direction>",
|
|
175
|
-
"Sort direction: ASC or DESC (default: DESC)",
|
|
176
|
-
"DESC"
|
|
177
|
-
)
|
|
178
|
-
.option(
|
|
179
|
-
"--start <offset>",
|
|
180
|
-
"Pagination offset (multiple of 50; default 0)",
|
|
181
|
-
(value) => Number(value),
|
|
182
|
-
0
|
|
183
|
-
)
|
|
184
|
-
.action(async (options) => {
|
|
185
|
-
const opts = program.opts();
|
|
186
|
-
const select =
|
|
187
|
-
parseList(options.select) || [
|
|
188
|
-
"ID",
|
|
189
|
-
"NAME",
|
|
190
|
-
"PROJECT",
|
|
191
|
-
"ACTIVE",
|
|
192
|
-
"VISIBLE",
|
|
193
|
-
"CLOSED",
|
|
194
|
-
];
|
|
195
|
-
const order = { [options.order]: options.dir.toUpperCase() };
|
|
196
|
-
const body = {
|
|
197
|
-
filter: { "%NAME": options.name },
|
|
198
|
-
select,
|
|
199
|
-
order,
|
|
200
|
-
start: options.start,
|
|
201
|
-
};
|
|
202
|
-
const data = await callBitrix(
|
|
203
|
-
"socialnetwork.api.workgroup.list",
|
|
204
|
-
body,
|
|
205
|
-
opts.base
|
|
206
|
-
);
|
|
207
|
-
console.log(JSON.stringify(data, null, 2));
|
|
208
|
-
});
|
|
158
|
+
case "search_groups": {
|
|
159
|
+
const body = {
|
|
160
|
+
filter: { "%NAME": args.name },
|
|
161
|
+
order: { ID: "DESC" },
|
|
162
|
+
start: args.start || 0,
|
|
163
|
+
};
|
|
164
|
+
const data = await callBitrix("socialnetwork.api.workgroup.list", body);
|
|
165
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
166
|
+
}
|
|
209
167
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
.requiredOption("--id <id>", "Workgroup identifier")
|
|
215
|
-
.option(
|
|
216
|
-
"--select <fields>",
|
|
217
|
-
"Comma‑separated list of fields to select (default includes common fields)",
|
|
218
|
-
undefined
|
|
219
|
-
)
|
|
220
|
-
.action(async (options) => {
|
|
221
|
-
const opts = program.opts();
|
|
222
|
-
const groupId = Number(options.id);
|
|
223
|
-
if (isNaN(groupId)) {
|
|
224
|
-
throw new Error("The --id option must be a number");
|
|
168
|
+
case "get_group": {
|
|
169
|
+
const body = { params: { groupId: args.id } };
|
|
170
|
+
const data = await callBitrix("socialnetwork.api.workgroup.get", body);
|
|
171
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
225
172
|
}
|
|
226
|
-
const select =
|
|
227
|
-
parseList(options.select) || [
|
|
228
|
-
"ACTIONS",
|
|
229
|
-
"AVATAR",
|
|
230
|
-
"AVATAR_DATA",
|
|
231
|
-
"COUNTERS",
|
|
232
|
-
"DATE_CREATE",
|
|
233
|
-
"DEPARTMENTS",
|
|
234
|
-
"EFFICIENCY",
|
|
235
|
-
"FEATURES",
|
|
236
|
-
"GROUP_MEMBERS_LIST",
|
|
237
|
-
"LIST_OF_MEMBERS",
|
|
238
|
-
"OWNER_DATA",
|
|
239
|
-
"PRIVACY_TYPE",
|
|
240
|
-
"SUBJECT_DATA",
|
|
241
|
-
"TAGS",
|
|
242
|
-
"USER_DATA",
|
|
243
|
-
];
|
|
244
|
-
const body = { params: { groupId, select } };
|
|
245
|
-
const data = await callBitrix(
|
|
246
|
-
"socialnetwork.api.workgroup.get",
|
|
247
|
-
body,
|
|
248
|
-
opts.base
|
|
249
|
-
);
|
|
250
|
-
console.log(JSON.stringify(data, null, 2));
|
|
251
|
-
});
|
|
252
173
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
} catch (
|
|
257
|
-
|
|
258
|
-
|
|
174
|
+
default:
|
|
175
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
176
|
+
}
|
|
177
|
+
} catch (error) {
|
|
178
|
+
return {
|
|
179
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
180
|
+
isError: true,
|
|
181
|
+
};
|
|
259
182
|
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Start the server
|
|
187
|
+
*/
|
|
188
|
+
async function main() {
|
|
189
|
+
const transport = new StdioServerTransport();
|
|
190
|
+
await server.connect(transport);
|
|
191
|
+
console.error("Bitrix24 MCP Server running on stdio");
|
|
260
192
|
}
|
|
261
193
|
|
|
262
|
-
main().catch((
|
|
263
|
-
console.error(
|
|
194
|
+
main().catch((error) => {
|
|
195
|
+
console.error("Fatal error in main():", error);
|
|
264
196
|
process.exit(1);
|
|
265
|
-
});
|
|
197
|
+
});
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x0333/bitrix24-mcp-server",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Bitrix24 MCP Server for AI Agent Integration.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"bitrix24-
|
|
7
|
+
"bitrix24-mcp": "index.js"
|
|
8
8
|
},
|
|
9
9
|
"type": "commonjs",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
12
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
13
|
+
"axios": "^1.5.0"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"mcp",
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
"automation"
|
|
21
21
|
],
|
|
22
22
|
"author": "Lukentui",
|
|
23
|
-
"license": "MIT",
|
|
24
23
|
"publishConfig": {
|
|
25
24
|
"access": "public"
|
|
26
25
|
}
|