@purplesquirrel/volcengine-mcp 1.0.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,21 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ open-pull-requests-limit: 10
8
+ labels:
9
+ - "dependencies"
10
+ commit-message:
11
+ prefix: "chore(deps)"
12
+
13
+ - package-ecosystem: "github-actions"
14
+ directory: "/"
15
+ schedule:
16
+ interval: "weekly"
17
+ labels:
18
+ - "dependencies"
19
+ - "github-actions"
20
+ commit-message:
21
+ prefix: "chore(ci)"
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+
13
+ strategy:
14
+ matrix:
15
+ node-version: [18.x, 20.x]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Use Node.js ${{ matrix.node-version }}
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ node-version: ${{ matrix.node-version }}
24
+ cache: 'npm'
25
+
26
+ - name: Install dependencies
27
+ run: npm ci
28
+
29
+ - name: Run linter
30
+ run: npm run lint --if-present
31
+
32
+ - name: Run tests
33
+ run: npm test --if-present
34
+
35
+ - name: Build
36
+ run: npm run build --if-present
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Purple Squirrel Media
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
2
+ [![MCP](https://img.shields.io/badge/MCP-Server-blue)](https://modelcontextprotocol.io)
3
+ [![Doubao](https://img.shields.io/badge/ByteDance-Doubao-00D1C1)](https://www.volcengine.com)
4
+ [![CI](https://github.com/PurpleSquirrelMedia/volcengine-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/PurpleSquirrelMedia/volcengine-mcp/actions/workflows/ci.yml)
5
+
6
+ # Volcano Engine MCP Server
7
+
8
+ MCP server for ByteDance Volcano Engine (Doubao) integration with Claude Code. Enables Claude to delegate tasks to ByteDance's Doubao LLM models.
9
+
10
+ ## Features
11
+
12
+ - **Text Generation** - Generate text using Doubao models
13
+ - **Chat** - Multi-turn conversations with Doubao
14
+ - **Embeddings** - Generate text embeddings for RAG and semantic search
15
+ - **Model Listing** - List available Doubao models
16
+
17
+ ## Available Tools (4 total)
18
+
19
+ | Tool | Description |
20
+ |------|-------------|
21
+ | `doubao_generate` | Generate text using Doubao models |
22
+ | `doubao_chat` | Multi-turn chat with Doubao models |
23
+ | `doubao_embeddings` | Generate text embeddings |
24
+ | `doubao_list_models` | List available models |
25
+
26
+ ## Setup
27
+
28
+ ### 1. Get Volcano Engine API Key
29
+
30
+ 1. Sign up at [console.volcengine.com](https://console.volcengine.com)
31
+ 2. Complete real-name authentication (required)
32
+ 3. Navigate to: **Large Models** → **Volcano Ark** → **API Key Management**
33
+ 4. Create and copy your API key
34
+
35
+ ### 2. Install Dependencies
36
+
37
+ ```bash
38
+ cd ~/mcp-servers/volcengine-mcp
39
+ npm install
40
+ ```
41
+
42
+ ### 3. Add to Claude Code
43
+
44
+ Add to `~/.claude.json`:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "volcengine": {
50
+ "type": "stdio",
51
+ "command": "node",
52
+ "args": ["/Users/matthewkarsten/mcp-servers/volcengine-mcp/index.js"],
53
+ "env": {
54
+ "ARK_API_KEY": "your-api-key-here"
55
+ }
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ ## Environment Variables
62
+
63
+ | Variable | Description | Required |
64
+ |----------|-------------|----------|
65
+ | `ARK_API_KEY` | Volcano Ark API key | Yes |
66
+ | `VOLCENGINE_API_KEY` | Alternative API key env var | Yes (if ARK_API_KEY not set) |
67
+ | `ARK_BASE_URL` | API base URL | No (defaults to Beijing region) |
68
+ | `ARK_CHAT_MODEL` | Default chat model | No (defaults to doubao-pro-32k) |
69
+ | `ARK_EMBEDDING_MODEL` | Default embedding model | No |
70
+
71
+ ## Available Models
72
+
73
+ ### Chat Models
74
+ | Model ID | Description | Context |
75
+ |----------|-------------|---------|
76
+ | `doubao-pro-32k` | General purpose, large context | 32K |
77
+ | `doubao-pro-4k` | General purpose, fast | 4K |
78
+ | `doubao-lite-32k` | Lightweight, large context | 32K |
79
+ | `doubao-lite-4k` | Lightweight, fast | 4K |
80
+ | `doubao-seed-1-6-250615` | Latest with vision support | 32K |
81
+ | `doubao-seed-1-6-flash-250615` | Fast thinking, low latency | 32K |
82
+ | `doubao-seed-1-6-thinking-250615` | Deep reasoning | 32K |
83
+
84
+ ### Embedding Models
85
+ | Model ID | Description | Dimensions |
86
+ |----------|-------------|------------|
87
+ | `doubao-embedding` | Text embeddings | 2560 |
88
+ | `doubao-embedding-text-240715` | Latest embeddings | 2560 |
89
+
90
+ ## Architecture
91
+
92
+ ```
93
+ Claude Code (Opus 4.5)
94
+
95
+ └──▶ Volcano Engine MCP Server
96
+
97
+ └──▶ Volcano Ark API
98
+
99
+ ├── Doubao Pro Models
100
+ ├── Doubao Lite Models
101
+ ├── Doubao Seed Models
102
+ └── Embedding Models
103
+ ```
104
+
105
+ ## Usage Examples
106
+
107
+ ```
108
+ User: Use Doubao to write a haiku about cloud computing
109
+
110
+ Claude: [Uses doubao_generate tool]
111
+ Result:
112
+ {
113
+ "text": "Servers hum softly\nData flows through endless clouds\nDigital rain falls",
114
+ "model": "doubao-pro-32k",
115
+ "usage": { "prompt_tokens": 12, "completion_tokens": 18 }
116
+ }
117
+ ```
118
+
119
+ ## Pricing
120
+
121
+ ByteDance Volcano Engine offers competitive pricing:
122
+
123
+ - **Free tier**: 500,000 tokens for individual users
124
+ - **Doubao Pro**: ~0.0008 CNY / 1K tokens (~$0.0001 USD)
125
+ - **Doubao Lite**: ~0.0003 CNY / 1K tokens
126
+
127
+ ## Multi-Agent Architecture
128
+
129
+ This MCP server enables a multi-agent system:
130
+
131
+ ```
132
+ Claude Code (Opus 4.5)
133
+
134
+ ├──▶ watsonx MCP Server (IBM Granite)
135
+ ├──▶ volcengine MCP Server (ByteDance Doubao)
136
+ └──▶ ibmz MCP Server (Key Protect HSM)
137
+ ```
138
+
139
+ Claude can delegate different tasks to specialized models based on:
140
+ - **Language**: Doubao excels at Chinese language tasks
141
+ - **Latency**: Doubao Flash for real-time applications
142
+ - **Reasoning**: Doubao Thinking for complex analysis
143
+ - **Cost**: Doubao Lite for high-volume tasks
144
+
145
+ ## Files
146
+
147
+ ```
148
+ volcengine-mcp/
149
+ ├── index.js # MCP server implementation
150
+ ├── package.json # Dependencies
151
+ └── README.md # This file
152
+ ```
153
+
154
+ ## Dependencies
155
+
156
+ - `@modelcontextprotocol/sdk` - MCP SDK
157
+
158
+ ## Author
159
+
160
+ Matthew Karsten
161
+
162
+ ## License
163
+
164
+ MIT
package/index.js ADDED
@@ -0,0 +1,418 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Volcano Engine (ByteDance) MCP Server
5
+ *
6
+ * Provides integration with ByteDance's Doubao LLM models via the Volcano Ark API.
7
+ * Enables Claude to delegate tasks to Doubao models for text generation, chat, and embeddings.
8
+ */
9
+
10
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
+ import {
13
+ CallToolRequestSchema,
14
+ ListToolsRequestSchema,
15
+ } from '@modelcontextprotocol/sdk/types.js';
16
+
17
+ // Configuration from environment variables
18
+ const ARK_API_KEY = process.env.ARK_API_KEY || process.env.VOLCENGINE_API_KEY;
19
+ const ARK_BASE_URL = process.env.ARK_BASE_URL || 'https://ark.cn-beijing.volces.com/api/v3';
20
+
21
+ // Default models
22
+ const DEFAULT_CHAT_MODEL = process.env.ARK_CHAT_MODEL || 'doubao-pro-32k';
23
+ const DEFAULT_EMBEDDING_MODEL = process.env.ARK_EMBEDDING_MODEL || 'doubao-embedding';
24
+
25
+ /**
26
+ * Make authenticated request to Volcano Ark API
27
+ */
28
+ async function arkRequest(endpoint, body, method = 'POST') {
29
+ if (!ARK_API_KEY) {
30
+ throw new Error('ARK_API_KEY or VOLCENGINE_API_KEY environment variable is required');
31
+ }
32
+
33
+ const response = await fetch(`${ARK_BASE_URL}${endpoint}`, {
34
+ method,
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ 'Authorization': `Bearer ${ARK_API_KEY}`,
38
+ },
39
+ body: method !== 'GET' ? JSON.stringify(body) : undefined,
40
+ });
41
+
42
+ if (!response.ok) {
43
+ const error = await response.text();
44
+ throw new Error(`Volcano Ark API error (${response.status}): ${error}`);
45
+ }
46
+
47
+ return response.json();
48
+ }
49
+
50
+ /**
51
+ * Generate text using Doubao models
52
+ */
53
+ async function generateText(prompt, options = {}) {
54
+ const {
55
+ model = DEFAULT_CHAT_MODEL,
56
+ max_tokens = 2048,
57
+ temperature = 0.7,
58
+ top_p = 0.9,
59
+ system_prompt = null,
60
+ } = options;
61
+
62
+ const messages = [];
63
+
64
+ if (system_prompt) {
65
+ messages.push({ role: 'system', content: system_prompt });
66
+ }
67
+
68
+ messages.push({ role: 'user', content: prompt });
69
+
70
+ const response = await arkRequest('/chat/completions', {
71
+ model,
72
+ messages,
73
+ max_tokens,
74
+ temperature,
75
+ top_p,
76
+ });
77
+
78
+ return {
79
+ text: response.choices?.[0]?.message?.content || '',
80
+ model: response.model,
81
+ usage: response.usage,
82
+ finish_reason: response.choices?.[0]?.finish_reason,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Chat with Doubao models (multi-turn conversation)
88
+ */
89
+ async function chat(messages, options = {}) {
90
+ const {
91
+ model = DEFAULT_CHAT_MODEL,
92
+ max_tokens = 2048,
93
+ temperature = 0.7,
94
+ top_p = 0.9,
95
+ } = options;
96
+
97
+ const response = await arkRequest('/chat/completions', {
98
+ model,
99
+ messages,
100
+ max_tokens,
101
+ temperature,
102
+ top_p,
103
+ });
104
+
105
+ return {
106
+ response: response.choices?.[0]?.message?.content || '',
107
+ model: response.model,
108
+ usage: response.usage,
109
+ finish_reason: response.choices?.[0]?.finish_reason,
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Generate embeddings using Doubao embedding models
115
+ */
116
+ async function generateEmbeddings(texts, options = {}) {
117
+ const { model = DEFAULT_EMBEDDING_MODEL } = options;
118
+
119
+ const input = Array.isArray(texts) ? texts : [texts];
120
+
121
+ const response = await arkRequest('/embeddings', {
122
+ model,
123
+ input,
124
+ });
125
+
126
+ return {
127
+ embeddings: response.data?.map(d => d.embedding) || [],
128
+ model: response.model,
129
+ usage: response.usage,
130
+ dimensions: response.data?.[0]?.embedding?.length || 0,
131
+ };
132
+ }
133
+
134
+ /**
135
+ * List available models (known Doubao models)
136
+ */
137
+ function listModels() {
138
+ // Volcano Ark doesn't have a public model list API, so we return known models
139
+ return {
140
+ models: [
141
+ {
142
+ id: 'doubao-pro-32k',
143
+ name: 'Doubao Pro 32K',
144
+ description: 'General purpose model with 32K context window',
145
+ type: 'chat',
146
+ context_length: 32768,
147
+ },
148
+ {
149
+ id: 'doubao-pro-4k',
150
+ name: 'Doubao Pro 4K',
151
+ description: 'General purpose model with 4K context window',
152
+ type: 'chat',
153
+ context_length: 4096,
154
+ },
155
+ {
156
+ id: 'doubao-lite-32k',
157
+ name: 'Doubao Lite 32K',
158
+ description: 'Lightweight model with 32K context window',
159
+ type: 'chat',
160
+ context_length: 32768,
161
+ },
162
+ {
163
+ id: 'doubao-lite-4k',
164
+ name: 'Doubao Lite 4K',
165
+ description: 'Lightweight model with 4K context window',
166
+ type: 'chat',
167
+ context_length: 4096,
168
+ },
169
+ {
170
+ id: 'doubao-seed-1-6-250615',
171
+ name: 'Doubao Seed 1.6',
172
+ description: 'Latest Doubao model with vision support for agents',
173
+ type: 'chat',
174
+ context_length: 32768,
175
+ },
176
+ {
177
+ id: 'doubao-seed-1-6-flash-250615',
178
+ name: 'Doubao Seed 1.6 Flash',
179
+ description: 'Fast thinking model with low latency',
180
+ type: 'chat',
181
+ context_length: 32768,
182
+ },
183
+ {
184
+ id: 'doubao-seed-1-6-thinking-250615',
185
+ name: 'Doubao Seed 1.6 Thinking',
186
+ description: 'Deep reasoning model for complex tasks',
187
+ type: 'chat',
188
+ context_length: 32768,
189
+ },
190
+ {
191
+ id: 'doubao-embedding',
192
+ name: 'Doubao Embedding',
193
+ description: 'Text embedding model',
194
+ type: 'embedding',
195
+ dimensions: 2560,
196
+ },
197
+ {
198
+ id: 'doubao-embedding-text-240715',
199
+ name: 'Doubao Embedding Text',
200
+ description: 'Latest text embedding model',
201
+ type: 'embedding',
202
+ dimensions: 2560,
203
+ },
204
+ ],
205
+ };
206
+ }
207
+
208
+ // Create MCP Server
209
+ const server = new Server(
210
+ {
211
+ name: 'volcengine-mcp-server',
212
+ version: '1.0.0',
213
+ },
214
+ {
215
+ capabilities: {
216
+ tools: {},
217
+ },
218
+ }
219
+ );
220
+
221
+ // Define available tools
222
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
223
+ return {
224
+ tools: [
225
+ {
226
+ name: 'doubao_generate',
227
+ description: 'Generate text using ByteDance Doubao models. Use for text completion, content generation, and single-turn tasks.',
228
+ inputSchema: {
229
+ type: 'object',
230
+ properties: {
231
+ prompt: {
232
+ type: 'string',
233
+ description: 'The prompt to send to the model',
234
+ },
235
+ model: {
236
+ type: 'string',
237
+ description: 'Model ID (e.g., doubao-pro-32k, doubao-lite-4k, doubao-seed-1-6-250615)',
238
+ default: DEFAULT_CHAT_MODEL,
239
+ },
240
+ max_tokens: {
241
+ type: 'number',
242
+ description: 'Maximum tokens to generate',
243
+ default: 2048,
244
+ },
245
+ temperature: {
246
+ type: 'number',
247
+ description: 'Sampling temperature (0-1)',
248
+ default: 0.7,
249
+ },
250
+ system_prompt: {
251
+ type: 'string',
252
+ description: 'Optional system prompt to set context',
253
+ },
254
+ },
255
+ required: ['prompt'],
256
+ },
257
+ },
258
+ {
259
+ name: 'doubao_chat',
260
+ description: 'Have a multi-turn conversation with Doubao models. Supports conversation history.',
261
+ inputSchema: {
262
+ type: 'object',
263
+ properties: {
264
+ messages: {
265
+ type: 'array',
266
+ description: 'Array of chat messages with role (system/user/assistant) and content',
267
+ items: {
268
+ type: 'object',
269
+ properties: {
270
+ role: {
271
+ type: 'string',
272
+ enum: ['system', 'user', 'assistant'],
273
+ },
274
+ content: {
275
+ type: 'string',
276
+ },
277
+ },
278
+ required: ['role', 'content'],
279
+ },
280
+ },
281
+ model: {
282
+ type: 'string',
283
+ description: 'Model ID to use',
284
+ default: DEFAULT_CHAT_MODEL,
285
+ },
286
+ max_tokens: {
287
+ type: 'number',
288
+ default: 2048,
289
+ },
290
+ temperature: {
291
+ type: 'number',
292
+ default: 0.7,
293
+ },
294
+ },
295
+ required: ['messages'],
296
+ },
297
+ },
298
+ {
299
+ name: 'doubao_embeddings',
300
+ description: 'Generate text embeddings using Doubao embedding models. Useful for semantic search and RAG.',
301
+ inputSchema: {
302
+ type: 'object',
303
+ properties: {
304
+ texts: {
305
+ type: 'array',
306
+ description: 'Array of texts to embed',
307
+ items: { type: 'string' },
308
+ },
309
+ model: {
310
+ type: 'string',
311
+ description: 'Embedding model ID',
312
+ default: DEFAULT_EMBEDDING_MODEL,
313
+ },
314
+ },
315
+ required: ['texts'],
316
+ },
317
+ },
318
+ {
319
+ name: 'doubao_list_models',
320
+ description: 'List available Doubao models from Volcano Engine',
321
+ inputSchema: {
322
+ type: 'object',
323
+ properties: {},
324
+ },
325
+ },
326
+ ],
327
+ };
328
+ });
329
+
330
+ // Handle tool calls
331
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
332
+ const { name, arguments: args } = request.params;
333
+
334
+ try {
335
+ switch (name) {
336
+ case 'doubao_generate': {
337
+ const result = await generateText(args.prompt, {
338
+ model: args.model,
339
+ max_tokens: args.max_tokens,
340
+ temperature: args.temperature,
341
+ system_prompt: args.system_prompt,
342
+ });
343
+ return {
344
+ content: [
345
+ {
346
+ type: 'text',
347
+ text: JSON.stringify(result, null, 2),
348
+ },
349
+ ],
350
+ };
351
+ }
352
+
353
+ case 'doubao_chat': {
354
+ const result = await chat(args.messages, {
355
+ model: args.model,
356
+ max_tokens: args.max_tokens,
357
+ temperature: args.temperature,
358
+ });
359
+ return {
360
+ content: [
361
+ {
362
+ type: 'text',
363
+ text: JSON.stringify(result, null, 2),
364
+ },
365
+ ],
366
+ };
367
+ }
368
+
369
+ case 'doubao_embeddings': {
370
+ const result = await generateEmbeddings(args.texts, {
371
+ model: args.model,
372
+ });
373
+ return {
374
+ content: [
375
+ {
376
+ type: 'text',
377
+ text: JSON.stringify(result, null, 2),
378
+ },
379
+ ],
380
+ };
381
+ }
382
+
383
+ case 'doubao_list_models': {
384
+ const result = listModels();
385
+ return {
386
+ content: [
387
+ {
388
+ type: 'text',
389
+ text: JSON.stringify(result, null, 2),
390
+ },
391
+ ],
392
+ };
393
+ }
394
+
395
+ default:
396
+ throw new Error(`Unknown tool: ${name}`);
397
+ }
398
+ } catch (error) {
399
+ return {
400
+ content: [
401
+ {
402
+ type: 'text',
403
+ text: `Error: ${error.message}`,
404
+ },
405
+ ],
406
+ isError: true,
407
+ };
408
+ }
409
+ });
410
+
411
+ // Start server
412
+ async function main() {
413
+ const transport = new StdioServerTransport();
414
+ await server.connect(transport);
415
+ console.error('Volcano Engine MCP Server running on stdio');
416
+ }
417
+
418
+ main().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@purplesquirrel/volcengine-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for ByteDance Volcano Engine (Doubao) integration with Claude Code",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "start": "node index.js"
9
+ },
10
+ "keywords": [
11
+ "mcp",
12
+ "volcano-engine",
13
+ "volcengine",
14
+ "bytedance",
15
+ "doubao",
16
+ "ai",
17
+ "llm"
18
+ ],
19
+ "author": "Matthew Karsten",
20
+ "license": "MIT",
21
+ "dependencies": {
22
+ "@modelcontextprotocol/sdk": "^1.24.0"
23
+ }
24
+ }