huggingface-mcp-server
Version:
MCP Server for HuggingFace inference endpoints with custom LoRA and story generation
172 lines (171 loc) • 7.28 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startServer = void 0;
exports.startHttpServer = startHttpServer;
const express_1 = __importDefault(require("express"));
const handler_1 = require("./handler");
/**
* Starts an HTTP server for MCP
* @param port The port to listen on
* @param apiKey The HuggingFace API key
* @returns A Promise that resolves when the server is started
*/
async function startHttpServer(port = 3000, apiKey) {
const app = (0, express_1.default)();
app.use(express_1.default.json());
// Log server startup
console.log(`Starting HuggingFace MCP Server in HTTP mode on port ${port}`);
console.log(`API Key is ${apiKey ? 'provided' : 'missing'}`);
// Add request logging middleware
app.use((req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
next();
});
const HUGGINGFACE_API_KEY = apiKey;
// Routes
app.get('/', (req, res) => {
res.json({ message: 'HuggingFace MCP Server is running' });
});
app.post('/v1/tools', (req, res) => {
const tools = [
{
type: 'function',
function: {
name: 'generate_image',
description: 'Generate an image based on a text prompt using Flux model, with optional custom LoRA',
parameters: {
type: 'object',
properties: {
prompt: {
type: 'string',
description: 'Description of the image to generate'
},
num_inference_steps: {
type: 'number',
description: 'The number of denoising steps of the image. More steps usually lead to higher quality at the cost of slower inference',
default: 25
},
height: {
type: 'number',
description: 'Height of the image in pixels',
default: 1024
},
width: {
type: 'number',
description: 'Width of the image in pixels',
default: 1024
},
guidance_scale: {
type: 'number',
description: 'Controls how much the image generation follows the text prompt. Higher values make the image stick more closely to the input text',
default: 3.5
},
seed: {
type: 'number',
description: 'A starting point to initiate the generation process, use 0 for a random seed',
default: 0
},
num_images_per_prompt: {
type: 'number',
description: 'Number of images to generate with the settings',
default: 1
},
lora_name: {
type: 'string',
description: 'Name of the custom LoRA model on HuggingFace (e.g., "username/lora-model-name")'
}
},
required: ['prompt']
}
}
},
{
type: 'function',
function: {
name: 'generate_story',
description: 'Generate a story based on a prompt',
parameters: {
type: 'object',
properties: {
prompt: {
type: 'string',
description: 'Prompt for story generation'
}
},
required: ['prompt']
}
}
}
];
// Log that tools were requested
console.log('Tools requested. Returning:', JSON.stringify(tools, null, 2));
res.json({ tools });
});
app.post('/v1/chat/completions', async (req, res) => {
const request = req.body;
const messages = request.messages;
// Check if the last message contains tool calls
const lastMessage = messages[messages.length - 1];
if (lastMessage.role === 'assistant' && lastMessage.tool_calls) {
const results = await (0, handler_1.handleToolCalls)(lastMessage.tool_calls, HUGGINGFACE_API_KEY);
return res.json({
id: 'chatcmpl-456',
object: 'chat.completion',
created: Math.floor(Date.now() / 1000),
model: 'hf-mcp-server',
choices: [{
index: 0,
message: {
role: 'assistant',
content: 'I\'ve processed your request.',
tool_calls: []
},
finish_reason: 'tool_calls'
}],
tool_responses: results
});
}
// If we reach here, return a response asking the user to choose a tool
res.json({
id: 'chatcmpl-123',
object: 'chat.completion',
created: Math.floor(Date.now() / 1000),
model: 'hf-mcp-server',
choices: [{
index: 0,
message: {
role: 'assistant',
tool_calls: [
{
id: 'call_abc123',
type: 'function',
function: {
name: 'generate_image',
arguments: JSON.stringify({
prompt: 'I need a description from you for the image you\'d like to generate.'
})
}
}
]
},
finish_reason: 'tool_calls'
}]
});
});
return new Promise((resolve, reject) => {
try {
app.listen(port, () => {
console.log(`HTTP Server running on port ${port}`);
resolve();
});
}
catch (error) {
reject(error);
}
});
}
// For backward compatibility, export startServer as an alias to startHttpServer
exports.startServer = startHttpServer;