# Directory Structure
```
├── .gitattributes
├── .gitignore
├── dist
│ ├── index.d.ts
│ └── index.js
├── icon.png
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── src
│ ├── index.ts
│ └── text-audio-api.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
```
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "module": "NodeNext",
5 | "moduleResolution": "NodeNext",
6 | "esModuleInterop": true,
7 | "outDir": "./dist",
8 | "rootDir": "./src",
9 | "strict": true,
10 | "declaration": true
11 | },
12 | "include": ["src/**/*"],
13 | "exclude": ["node_modules", "dist"]
14 | }
15 |
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "pollinations-mcp",
3 | "version": "1.0.0",
4 | "main": "dist/index.js",
5 | "type": "module",
6 | "scripts": {
7 | "build": "tsc",
8 | "start": "node dist/index.js",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "keywords": [
12 | "mcp",
13 | "pollinations",
14 | "ai",
15 | "image",
16 | "generation"
17 | ],
18 | "author": "bendusy",
19 | "license": "ISC",
20 | "description": "使用MCP协议连接Pollinations.ai的图像生成服务",
21 | "dependencies": {
22 | "@modelcontextprotocol/sdk": "^1.6.1",
23 | "axios": "^1.8.1"
24 | },
25 | "devDependencies": {
26 | "@types/node": "^22.13.9",
27 | "typescript": "^5.8.2"
28 | },
29 | "repository": {
30 | "type": "git",
31 | "url": "https://github.com/bendusy/pollinations-mcp.git"
32 | },
33 | "homepage": "https://github.com/bendusy/pollinations-mcp",
34 | "bugs": {
35 | "url": "https://github.com/bendusy/pollinations-mcp/issues"
36 | },
37 | "icon": "icon.png"
38 | }
39 |
```
--------------------------------------------------------------------------------
/src/text-audio-api.ts:
--------------------------------------------------------------------------------
```typescript
1 | import axios from 'axios';
2 | import * as fs from 'fs';
3 | import * as path from 'path';
4 |
5 | /**
6 | * Pollinations文本API实现
7 | */
8 | export class PollinationsTextAudioAPI {
9 | private baseTextUrl = 'https://text.pollinations.ai';
10 |
11 | /**
12 | * 生成文本 (GET方法)
13 | * @param prompt 提示词
14 | * @param options 选项
15 | * @returns 生成的文本
16 | */
17 | async generateTextGet(prompt: string, options: {
18 | model?: string;
19 | seed?: number;
20 | json?: boolean;
21 | system?: string;
22 | private?: boolean;
23 | } = {}) {
24 | const { model = 'openai', seed, json = false, system, private: isPrivate = false } = options;
25 |
26 | let url = `${this.baseTextUrl}/${encodeURIComponent(prompt)}?model=${model}`;
27 |
28 | if (seed !== undefined) {
29 | url += `&seed=${seed}`;
30 | }
31 |
32 | if (json) {
33 | url += `&json=true`;
34 | }
35 |
36 | if (system) {
37 | url += `&system=${encodeURIComponent(system)}`;
38 | }
39 |
40 | if (isPrivate) {
41 | url += `&private=true`;
42 | }
43 |
44 | try {
45 | const response = await axios.get(url);
46 | return response.data;
47 | } catch (error) {
48 | throw new Error(`文本生成失败: ${error instanceof Error ? error.message : String(error)}`);
49 | }
50 | }
51 |
52 | /**
53 | * 生成文本 (POST方法)
54 | * @param messages 消息数组
55 | * @param options 选项
56 | * @returns 生成的文本
57 | */
58 | async generateTextPost(messages: Array<{role: string, content: string | Array<{type: string, text?: string, image_url?: {url: string}}>}>, options: {
59 | model?: string;
60 | seed?: number;
61 | jsonMode?: boolean;
62 | private?: boolean;
63 | } = {}) {
64 | const { model = 'openai', seed, jsonMode = false, private: isPrivate = false } = options;
65 |
66 | try {
67 | const response = await axios.post(`${this.baseTextUrl}/`, {
68 | messages,
69 | model,
70 | seed,
71 | jsonMode,
72 | private: isPrivate
73 | });
74 | return response.data;
75 | } catch (error) {
76 | throw new Error(`文本生成失败: ${error instanceof Error ? error.message : String(error)}`);
77 | }
78 | }
79 |
80 | /**
81 | * 获取可用模型列表
82 | * @param type 模型类型 ('text')
83 | * @returns 模型列表
84 | */
85 | async getAvailableModels(type: 'text' = 'text') {
86 | try {
87 | const url = `${this.baseTextUrl}/models`;
88 |
89 | const response = await axios.get(url);
90 | return response.data;
91 | } catch (error) {
92 | throw new Error(`获取模型列表失败: ${error instanceof Error ? error.message : String(error)}`);
93 | }
94 | }
95 | }
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | #!/usr/bin/env node
2 | import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4 | import {
5 | CallToolRequestSchema,
6 | ErrorCode,
7 | ListToolsRequestSchema,
8 | McpError,
9 | } from '@modelcontextprotocol/sdk/types.js';
10 | import axios from 'axios';
11 | import * as fs from 'fs';
12 | import * as path from 'path';
13 |
14 | // 简化的错误类型枚举
15 | enum PollinationsErrorType {
16 | VALIDATION_ERROR = 'VALIDATION_ERROR',
17 | API_ERROR = 'API_ERROR',
18 | FILE_SYSTEM_ERROR = 'FILE_SYSTEM_ERROR'
19 | }
20 |
21 | // 简化的错误类
22 | class PollinationsError extends Error {
23 | type: PollinationsErrorType;
24 | statusCode?: number;
25 |
26 | constructor(message: string, type: PollinationsErrorType, statusCode?: number) {
27 | super(message);
28 | this.name = 'PollinationsError';
29 | this.type = type;
30 | this.statusCode = statusCode;
31 | }
32 |
33 | toUserFriendlyMessage(): string {
34 | return `错误: ${this.message}${this.statusCode ? ` (状态码: ${this.statusCode})` : ''}`;
35 | }
36 | }
37 |
38 | // Pollinations文本API实现
39 | class PollinationsTextAPI {
40 | private baseTextUrl = 'https://text.pollinations.ai';
41 |
42 | /**
43 | * 生成文本 (GET方法)
44 | * @param prompt 提示词
45 | * @param options 选项
46 | * @returns 生成的文本
47 | */
48 | async generateTextGet(prompt: string, options: {
49 | model?: string;
50 | seed?: number;
51 | json?: boolean;
52 | system?: string;
53 | private?: boolean;
54 | } = {}) {
55 | const { model = 'openai', seed, json = false, system, private: isPrivate = false } = options;
56 |
57 | let url = `${this.baseTextUrl}/${encodeURIComponent(prompt)}?model=${model}`;
58 |
59 | if (seed !== undefined) {
60 | url += `&seed=${seed}`;
61 | }
62 |
63 | if (json) {
64 | url += `&json=true`;
65 | }
66 |
67 | if (system) {
68 | url += `&system=${encodeURIComponent(system)}`;
69 | }
70 |
71 | if (isPrivate) {
72 | url += `&private=true`;
73 | }
74 |
75 | try {
76 | const response = await axios.get(url);
77 | return response.data;
78 | } catch (error) {
79 | throw new Error(`文本生成失败: ${error instanceof Error ? error.message : String(error)}`);
80 | }
81 | }
82 |
83 | /**
84 | * 获取可用模型列表
85 | * @returns 模型列表
86 | */
87 | async getAvailableModels() {
88 | try {
89 | const url = `${this.baseTextUrl}/models`;
90 |
91 | const response = await axios.get(url);
92 | return response.data;
93 | } catch (error) {
94 | throw new Error(`获取模型列表失败: ${error instanceof Error ? error.message : String(error)}`);
95 | }
96 | }
97 | }
98 |
99 | // Pollinations.ai 服务器实现
100 | class PollinationsServer {
101 | private server: Server;
102 | private baseUrl = 'https://image.pollinations.ai';
103 | private textAPI: PollinationsTextAPI;
104 |
105 | constructor() {
106 | this.server = new Server(
107 | {
108 | name: 'pollinations-mcp-server',
109 | version: '0.1.0',
110 | },
111 | {
112 | capabilities: {
113 | tools: {},
114 | },
115 | }
116 | );
117 |
118 | // 初始化文本API
119 | this.textAPI = new PollinationsTextAPI();
120 |
121 | // 设置工具处理器
122 | this.setupToolHandlers();
123 |
124 | // 错误处理
125 | this.server.onerror = (error) => console.error('[MCP Error]', error);
126 | process.on('SIGINT', async () => {
127 | await this.server.close();
128 | process.exit(0);
129 | });
130 | }
131 |
132 | // 错误处理方法
133 | private handleValidationError(message: string): PollinationsError {
134 | return new PollinationsError(message, PollinationsErrorType.VALIDATION_ERROR, 400);
135 | }
136 |
137 | private handleApiError(error: any): PollinationsError {
138 | if (axios.isAxiosError(error)) {
139 | const statusCode = error.response?.status || 0;
140 | const message = error.response?.data?.message || error.message;
141 | return new PollinationsError(`API错误: ${message}`, PollinationsErrorType.API_ERROR, statusCode);
142 | }
143 | return new PollinationsError(`未知错误: ${error.message || error}`, PollinationsErrorType.API_ERROR, 0);
144 | }
145 |
146 | private handleFileSystemError(error: any, operation: string): PollinationsError {
147 | return new PollinationsError(`文件操作失败 (${operation}): ${error.message || error}`, PollinationsErrorType.FILE_SYSTEM_ERROR);
148 | }
149 |
150 | // 设置MCP工具处理器
151 | private setupToolHandlers() {
152 | // 列出可用工具
153 | this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
154 | tools: [
155 | {
156 | name: 'generate_image',
157 | description: '使用Pollinations.ai生成图像',
158 | inputSchema: {
159 | type: 'object',
160 | properties: {
161 | prompt: {
162 | type: 'string',
163 | description: '图像描述提示词',
164 | },
165 | width: {
166 | type: 'number',
167 | description: '图像宽度(像素)',
168 | default: 1024,
169 | },
170 | height: {
171 | type: 'number',
172 | description: '图像高度(像素)',
173 | default: 1024,
174 | },
175 | seed: {
176 | type: 'number',
177 | description: '随机种子值(用于生成一致的图像)',
178 | },
179 | model: {
180 | type: 'string',
181 | description: '要使用的模型(如flux、variation等)',
182 | default: 'flux',
183 | },
184 | nologo: {
185 | type: 'boolean',
186 | description: '设置为true可去除水印',
187 | default: true,
188 | },
189 | enhance: {
190 | type: 'boolean',
191 | description: '提高图像质量(应用增强滤镜)',
192 | default: false,
193 | },
194 | safe: {
195 | type: 'boolean',
196 | description: '启用安全过滤(过滤不适内容)',
197 | default: false,
198 | },
199 | private: {
200 | type: 'boolean',
201 | description: '设置为true可使图像私有',
202 | default: false,
203 | },
204 | },
205 | required: ['prompt'],
206 | },
207 | },
208 | {
209 | name: 'download_image',
210 | description: '下载Pollinations.ai生成的图像到本地文件',
211 | inputSchema: {
212 | type: 'object',
213 | properties: {
214 | url: {
215 | type: 'string',
216 | description: '要下载的图像URL',
217 | },
218 | output_path: {
219 | type: 'string',
220 | description: '保存图像的路径(包括文件名)',
221 | default: 'image.jpg',
222 | },
223 | },
224 | required: ['url'],
225 | },
226 | },
227 | {
228 | name: 'generate_text',
229 | description: '使用Pollinations.ai生成文本',
230 | inputSchema: {
231 | type: 'object',
232 | properties: {
233 | prompt: {
234 | type: 'string',
235 | description: '文本提示词',
236 | },
237 | model: {
238 | type: 'string',
239 | description: '要使用的模型(如openai、mistral等)',
240 | default: 'openai',
241 | },
242 | seed: {
243 | type: 'number',
244 | description: '随机种子值(用于生成一致的结果)',
245 | },
246 | system: {
247 | type: 'string',
248 | description: '系统提示词(设置AI行为)',
249 | },
250 | json: {
251 | type: 'boolean',
252 | description: '是否返回JSON格式的响应',
253 | default: false,
254 | },
255 | private: {
256 | type: 'boolean',
257 | description: '设置为true可使响应私有',
258 | default: false,
259 | },
260 | },
261 | required: ['prompt'],
262 | },
263 | },
264 | ],
265 | }));
266 |
267 | // 处理工具调用
268 | this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
269 | switch (request.params.name) {
270 | case 'generate_image':
271 | return this.handleGenerateImage(request.params.arguments);
272 | case 'download_image':
273 | return this.handleDownloadImage(request.params.arguments);
274 | case 'generate_text':
275 | return this.handleGenerateText(request.params.arguments);
276 | default:
277 | throw new McpError(
278 | ErrorCode.MethodNotFound,
279 | `未知工具: ${request.params.name}`
280 | );
281 | }
282 | });
283 | }
284 |
285 | // 处理生成图像请求
286 | private async handleGenerateImage(args: any) {
287 | try {
288 | if (!this.isValidGenerateImageArgs(args)) {
289 | throw this.handleValidationError('无效的图像生成参数');
290 | }
291 |
292 | const {
293 | prompt,
294 | width = 1024,
295 | height = 1024,
296 | seed,
297 | model = 'flux',
298 | nologo = true,
299 | enhance = false,
300 | safe = false,
301 | private: isPrivate = false
302 | } = args;
303 |
304 | // 检查提示词是否为英文
305 | const isMainlyEnglish = this.isMainlyEnglish(prompt);
306 | const isConcise = prompt.length <= 200;
307 |
308 | let promptFeedback = '';
309 |
310 | if (!isMainlyEnglish) {
311 | promptFeedback += '提示:Pollinations.ai对英文提示词的理解更好,建议使用英文编写提示词。\n';
312 | }
313 |
314 | if (!isConcise) {
315 | promptFeedback += '提示:提示词过长可能影响生成效果,建议保持简短精确(建议不超过200字符)。\n';
316 | }
317 |
318 | // 构建Pollinations URL(使用官方路径格式)
319 | let imageUrl = `${this.baseUrl}/prompt/${encodeURIComponent(prompt)}?width=${width}&height=${height}`;
320 |
321 | if (seed !== undefined) {
322 | imageUrl += `&seed=${seed}`;
323 | }
324 |
325 | if (model) {
326 | imageUrl += `&model=${model}`;
327 | }
328 |
329 | if (nologo) {
330 | imageUrl += `&nologo=true`;
331 | }
332 |
333 | // 添加新参数支持
334 | if (enhance) {
335 | imageUrl += `&enhance=true`;
336 | }
337 |
338 | if (safe) {
339 | imageUrl += `&safe=true`;
340 | }
341 |
342 | if (isPrivate) {
343 | imageUrl += `&private=true`;
344 | }
345 |
346 | // 验证URL是否有效
347 | try {
348 | // 发送HEAD请求检查URL是否可访问(不下载完整图像)
349 | await axios.head(imageUrl);
350 | } catch (error) {
351 | // 处理API错误
352 | const pollinationsError = this.handleApiError(error);
353 |
354 | // 特殊处理安全过滤错误
355 | if (pollinationsError.statusCode === 400 && safe) {
356 | throw new PollinationsError(
357 | '内容被安全过滤拦截,请修改提示词后重试',
358 | PollinationsErrorType.VALIDATION_ERROR,
359 | 400
360 | );
361 | }
362 |
363 | throw pollinationsError;
364 | }
365 |
366 | const response = {
367 | content: [
368 | {
369 | type: 'text',
370 | text: JSON.stringify({
371 | url: imageUrl,
372 | prompt,
373 | width,
374 | height,
375 | seed,
376 | model,
377 | nologo,
378 | enhance,
379 | safe,
380 | private: isPrivate
381 | }, null, 2),
382 | },
383 | ],
384 | };
385 |
386 | // 如果有提示反馈,添加到响应中
387 | if (promptFeedback) {
388 | response.content.unshift({
389 | type: 'text',
390 | text: promptFeedback
391 | });
392 | }
393 |
394 | return response;
395 | } catch (error) {
396 | // 处理所有错误
397 | let pollinationsError: PollinationsError;
398 |
399 | if (error instanceof PollinationsError) {
400 | pollinationsError = error;
401 | } else {
402 | pollinationsError = this.handleApiError(error);
403 | }
404 |
405 | return {
406 | content: [
407 | {
408 | type: 'text',
409 | text: pollinationsError.toUserFriendlyMessage(),
410 | },
411 | ],
412 | isError: true,
413 | };
414 | }
415 | }
416 |
417 | // 检查文本是否主要为英文
418 | private isMainlyEnglish(text: string): boolean {
419 | // 英文字符(包括空格和标点)的正则表达式
420 | const englishRegex = /^[A-Za-z0-9\s.,;:'"!?()-]+$/;
421 |
422 | // 如果完全匹配英文字符,返回true
423 | if (englishRegex.test(text)) {
424 | return true;
425 | }
426 |
427 | // 否则计算非英文字符的比例
428 | const nonEnglishChars = text.split('').filter(char => !char.match(/[A-Za-z0-9\s.,;:'"!?()-]/)).length;
429 | const totalChars = text.length;
430 |
431 | // 如果非英文字符少于20%,仍然视为主要是英文
432 | return (nonEnglishChars / totalChars) < 0.2;
433 | }
434 |
435 | // 处理下载图像请求
436 | private async handleDownloadImage(args: any) {
437 | try {
438 | if (!this.isValidDownloadImageArgs(args)) {
439 | throw this.handleValidationError('无效的图像下载参数');
440 | }
441 |
442 | // 获取参数
443 | let { url, output_path = 'image.jpg' } = args;
444 |
445 | // 使用相对路径保存图像到当前工作目录
446 | output_path = path.resolve(process.cwd(), output_path);
447 | console.error(`图像将保存到: ${output_path}`);
448 |
449 | try {
450 | // 确保输出目录存在
451 | const dirname = path.dirname(output_path);
452 | if (!fs.existsSync(dirname)) {
453 | console.error(`创建目录: ${dirname}`);
454 | fs.mkdirSync(dirname, { recursive: true });
455 | }
456 | } catch (fsError) {
457 | throw this.handleFileSystemError(fsError, '创建目录');
458 | }
459 |
460 | // 下载图像
461 | console.error(`开始下载图像: ${url}`);
462 | let response;
463 | try {
464 | response = await axios.get(url, { responseType: 'arraybuffer' });
465 | } catch (downloadError) {
466 | throw this.handleApiError(downloadError);
467 | }
468 |
469 | // 写入文件
470 | try {
471 | console.error(`写入文件: ${output_path}`);
472 | fs.writeFileSync(output_path, Buffer.from(response.data, 'binary'));
473 | } catch (writeError) {
474 | throw this.handleFileSystemError(writeError, '写入文件');
475 | }
476 |
477 | // 验证文件是否写入成功
478 | try {
479 | if (fs.existsSync(output_path)) {
480 | const fileSize = fs.statSync(output_path).size;
481 | console.error(`文件成功写入: ${output_path}, 大小: ${fileSize} 字节`);
482 |
483 | return {
484 | content: [
485 | {
486 | type: 'text',
487 | text: JSON.stringify({
488 | success: true,
489 | message: `图像已下载到 ${output_path}`,
490 | size: fileSize,
491 | path: output_path
492 | }, null, 2),
493 | },
494 | ],
495 | };
496 | } else {
497 | throw new PollinationsError(
498 | `文件写入失败: ${output_path}`,
499 | PollinationsErrorType.FILE_SYSTEM_ERROR
500 | );
501 | }
502 | } catch (verifyError) {
503 | if (verifyError instanceof PollinationsError) {
504 | throw verifyError;
505 | } else {
506 | throw this.handleFileSystemError(verifyError, '验证文件');
507 | }
508 | }
509 | } catch (error) {
510 | // 处理所有错误
511 | let pollinationsError: PollinationsError;
512 |
513 | if (error instanceof PollinationsError) {
514 | pollinationsError = error;
515 | } else {
516 | pollinationsError = this.handleApiError(error);
517 | }
518 |
519 | return {
520 | content: [
521 | {
522 | type: 'text',
523 | text: pollinationsError.toUserFriendlyMessage(),
524 | },
525 | ],
526 | isError: true,
527 | };
528 | }
529 | }
530 |
531 | // 验证生成图像参数
532 | private isValidGenerateImageArgs(args: any): args is {
533 | prompt: string;
534 | width?: number;
535 | height?: number;
536 | seed?: number;
537 | model?: string;
538 | nologo?: boolean;
539 | enhance?: boolean;
540 | safe?: boolean;
541 | private?: boolean;
542 | } {
543 | return (
544 | typeof args === 'object' &&
545 | args !== null &&
546 | typeof args.prompt === 'string' &&
547 | (args.width === undefined || typeof args.width === 'number') &&
548 | (args.height === undefined || typeof args.height === 'number') &&
549 | (args.seed === undefined || typeof args.seed === 'number') &&
550 | (args.model === undefined || typeof args.model === 'string') &&
551 | (args.nologo === undefined || typeof args.nologo === 'boolean') &&
552 | (args.enhance === undefined || typeof args.enhance === 'boolean') &&
553 | (args.safe === undefined || typeof args.safe === 'boolean') &&
554 | (args.private === undefined || typeof args.private === 'boolean')
555 | );
556 | }
557 |
558 | // 验证下载图像参数
559 | private isValidDownloadImageArgs(args: any): args is {
560 | url: string;
561 | output_path?: string;
562 | } {
563 | return (
564 | typeof args === 'object' &&
565 | args !== null &&
566 | typeof args.url === 'string' &&
567 | (args.output_path === undefined || typeof args.output_path === 'string')
568 | );
569 | }
570 |
571 | // 处理生成文本请求
572 | private async handleGenerateText(args: any) {
573 | try {
574 | if (!this.isValidGenerateTextArgs(args)) {
575 | throw this.handleValidationError('无效的文本生成参数');
576 | }
577 |
578 | const { prompt, model = 'openai', seed, system, json = false, private: isPrivate = false } = args;
579 |
580 | const result = await this.textAPI.generateTextGet(prompt, {
581 | model,
582 | seed,
583 | json,
584 | system,
585 | private: isPrivate
586 | });
587 |
588 | return {
589 | content: [
590 | {
591 | type: 'text',
592 | text: typeof result === 'string' ? result : JSON.stringify(result, null, 2),
593 | },
594 | ],
595 | };
596 | } catch (error) {
597 | // 处理所有错误
598 | let pollinationsError: PollinationsError;
599 |
600 | if (error instanceof PollinationsError) {
601 | pollinationsError = error;
602 | } else {
603 | pollinationsError = this.handleApiError(error);
604 | }
605 |
606 | return {
607 | content: [
608 | {
609 | type: 'text',
610 | text: pollinationsError.toUserFriendlyMessage(),
611 | },
612 | ],
613 | isError: true,
614 | };
615 | }
616 | }
617 |
618 | // 验证生成文本参数
619 | private isValidGenerateTextArgs(args: any): args is {
620 | prompt: string;
621 | model?: string;
622 | seed?: number;
623 | system?: string;
624 | json?: boolean;
625 | private?: boolean;
626 | } {
627 | return (
628 | typeof args === 'object' &&
629 | args !== null &&
630 | typeof args.prompt === 'string' &&
631 | (args.model === undefined || typeof args.model === 'string') &&
632 | (args.seed === undefined || typeof args.seed === 'number') &&
633 | (args.system === undefined || typeof args.system === 'string') &&
634 | (args.json === undefined || typeof args.json === 'boolean') &&
635 | (args.private === undefined || typeof args.private === 'boolean')
636 | );
637 | }
638 |
639 | // 运行服务器
640 | async run() {
641 | const transport = new StdioServerTransport();
642 | await this.server.connect(transport);
643 | console.error('Pollinations MCP服务器正在通过stdio运行');
644 | }
645 | }
646 |
647 | // 创建并运行服务器
648 | const server = new PollinationsServer();
649 | server.run().catch(console.error);
650 |
```