index.ts•4.94 kB
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ErrorCode,
ListToolsRequestSchema,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
import { LogoExtractor } from './logo-extractor.js';
import { ImageProcessor } from './image-processor.js';
import fs from 'fs';
import path from 'path';
import parseUrl from 'url-parse';
/**
* Logo MCP 服务器
* 提供智能Logo提取和处理功能
*/
class LogoMCPServer {
private server: Server;
private logoExtractor: LogoExtractor;
private imageProcessor: ImageProcessor;
constructor() {
this.server = new Server(
{
name: 'logo-mcp',
version: '2.0.0',
},
{
capabilities: {
tools: {}
}
}
);
this.logoExtractor = new LogoExtractor();
this.imageProcessor = new ImageProcessor();
this.setupToolHandlers();
}
private setupToolHandlers() {
// 列出可用工具
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'get_best_logo_url',
description: '从网站提取并返回最佳Logo的URL地址,适用于只需要获取最佳Logo URL的场景',
inputSchema: {
type: 'object',
properties: {
url: {
type: 'string',
description: '要分析的网站URL',
},
},
required: ['url'],
},
},
{
name: 'analyze_logo',
description: '分析Logo的基本信息(尺寸、格式、质量等),支持onlyBestUrl参数只返回最佳Logo的URL',
inputSchema: {
type: 'object',
properties: {
url: {
type: 'string',
description: '要分析的网站URL',
},
onlyBestUrl: {
type: 'boolean',
description: '是否只返回最佳Logo的URL,默认为false',
default: false,
},
},
required: ['url'],
},
},
],
};
});
// 处理工具调用
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'get_best_logo_url':
return await this.handleGetBestLogoUrl(args);
case 'analyze_logo':
return await this.handleAnalyzeLogo(args);
default:
throw new McpError(
ErrorCode.MethodNotFound,
`未知工具: ${name}`
);
}
} catch (error) {
throw new McpError(
ErrorCode.InternalError,
`工具执行失败: ${error instanceof Error ? error.message : String(error)}`
);
}
});
}
private async handleGetBestLogoUrl(args: any) {
const { url } = args;
const analysis = await this.logoExtractor.analyzeLogo(url);
// 统一错误处理方式,与analyze_logo保持一致
if (analysis.status === 'failed' || !analysis.bestCandidate) {
return {
content: [
{
type: 'text',
text: `无法从 ${url} 找到Logo。请检查网站是否存在Logo或网络连接是否正常。`,
},
],
};
}
return {
content: [
{
type: 'text',
text: analysis.bestCandidate.url,
},
],
};
}
private async handleAnalyzeLogo(args: any) {
const { url, onlyBestUrl = false } = args;
const analysis = await this.logoExtractor.analyzeLogo(url);
if (onlyBestUrl) {
// 只返回最佳Logo URL
if (analysis.status === 'failed' || !analysis.bestCandidate) {
return {
content: [
{
type: 'text',
text: `无法从 ${url} 找到Logo。请检查网站是否存在Logo或网络连接是否正常。`,
},
],
};
}
return {
content: [
{
type: 'text',
text: analysis.bestCandidate.url,
},
],
};
} else {
// 返回完整分析结果
return {
content: [
{
type: 'text',
text: `Logo分析结果:\n${JSON.stringify(analysis, null, 2)}`,
},
],
};
}
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Logo MCP 服务器已启动');
}
}
// 启动服务器
const server = new LogoMCPServer();
server.run().catch(console.error);