marketing-post-generator-mcp
Version:
A powerful MCP server for AI-powered marketing blog post generation with Claude integration
301 lines • 11.3 kB
JavaScript
import { VersionManager } from './VersionManager.js';
/**
* Service for discovering and exploring available tools and prompts
*/
export class DiscoveryService {
versionManager;
constructor(versionManager) {
this.versionManager = versionManager || new VersionManager();
}
/**
* Discover tools and prompts based on query criteria
*/
discover(toolEntries, promptEntries, query = {}) {
// Collect all entries based on type filter
const allEntries = [];
if (query.type === 'tool' || query.type === undefined || query.type === 'all') {
allEntries.push(...Array.from(toolEntries.values()));
}
if (query.type === 'prompt' || query.type === undefined || query.type === 'all') {
allEntries.push(...Array.from(promptEntries.values()));
}
// Apply filters
let filteredEntries = this.applyFilters(allEntries, query);
// Apply sorting
filteredEntries = this.applySorting(filteredEntries, query);
// Calculate pagination
const total = filteredEntries.length;
const limit = query.limit || 50;
const offset = query.offset || 0;
const hasMore = offset + limit < total;
// Apply pagination
const paginatedEntries = filteredEntries.slice(offset, offset + limit);
// Convert to discovery entries
const discoveryEntries = this.convertToDiscoveryEntries(paginatedEntries);
// Generate metadata
const metadata = this.generateDiscoveryMetadata(toolEntries, promptEntries, query);
return {
entries: discoveryEntries,
metadata,
pagination: {
total,
limit,
offset,
hasMore,
},
};
}
/**
* Search for tools and prompts by text
*/
search(toolEntries, promptEntries, searchText, options = {}) {
return this.discover(toolEntries, promptEntries, {
...options,
searchText: searchText.toLowerCase(),
});
}
/**
* Get tools and prompts by specific tags
*/
getByTags(toolEntries, promptEntries, tags, options = {}) {
return this.discover(toolEntries, promptEntries, {
...options,
tags,
});
}
/**
* Get tools and prompts by author
*/
getByAuthor(toolEntries, promptEntries, author, options = {}) {
return this.discover(toolEntries, promptEntries, {
...options,
author,
});
}
/**
* Get compatible tools and prompts for a specific version
*/
getCompatibleEntries(toolEntries, promptEntries, targetVersion, options = {}) {
const versionString = this.versionManager.formatVersion(targetVersion);
return this.discover(toolEntries, promptEntries, {
...options,
versionRange: `^${versionString}`,
});
}
/**
* Get recently created or updated entries
*/
getRecent(toolEntries, promptEntries, days = 30, options = {}) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - days);
const allEntries = [
...Array.from(toolEntries.values()),
...Array.from(promptEntries.values()),
];
const recentEntries = allEntries.filter((entry) => entry.createdAt >= cutoffDate || entry.updatedAt >= cutoffDate);
// Convert to map format for discovery method
const recentToolEntries = new Map();
const recentPromptEntries = new Map();
recentEntries.forEach((entry) => {
if (entry.type === 'tool') {
recentToolEntries.set(entry.name, entry);
}
else {
recentPromptEntries.set(entry.name, entry);
}
});
return this.discover(recentToolEntries, recentPromptEntries, {
...options,
sortBy: 'updated',
sortOrder: 'desc',
});
}
/**
* Get deprecated entries
*/
getDeprecated(toolEntries, promptEntries, options = {}) {
return this.discover(toolEntries, promptEntries, {
...options,
deprecated: true,
});
}
/**
* Get available categories (tags)
*/
getCategories(toolEntries, promptEntries) {
const categories = new Set();
// Collect tags from tools
toolEntries.forEach((tool) => {
tool.tags?.forEach((tag) => categories.add(tag));
});
// Collect tags from prompts
promptEntries.forEach((prompt) => {
prompt.tags?.forEach((tag) => categories.add(tag));
});
return Array.from(categories).sort();
}
/**
* Get statistics about available entries
*/
getStatistics(toolEntries, promptEntries) {
const allEntries = [
...Array.from(toolEntries.values()),
...Array.from(promptEntries.values()),
];
const authors = new Set();
const categories = new Set();
let deprecatedCount = 0;
const totalVersion = { major: 0, minor: 0, patch: 0 };
let latestVersion = { major: 0, minor: 0, patch: 0 };
allEntries.forEach((entry) => {
if (entry.author)
authors.add(entry.author);
entry.tags?.forEach((tag) => categories.add(tag));
if (entry.deprecated)
deprecatedCount++;
totalVersion.major += entry.version.major;
totalVersion.minor += entry.version.minor;
totalVersion.patch += entry.version.patch;
if (this.versionManager.compareVersions(entry.version, latestVersion) > 0) {
latestVersion = entry.version;
}
});
const count = allEntries.length || 1;
const averageVersion = {
major: Math.round(totalVersion.major / count),
minor: Math.round(totalVersion.minor / count),
patch: Math.round(totalVersion.patch / count),
};
return {
tools: toolEntries.size,
prompts: promptEntries.size,
total: allEntries.length,
deprecated: deprecatedCount,
categories: categories.size,
authors: authors.size,
averageVersion: this.versionManager.formatVersion(averageVersion),
latestVersion: this.versionManager.formatVersion(latestVersion),
};
}
// Private helper methods
applyFilters(entries, query) {
return entries.filter((entry) => {
// Type filter
if (query.type && query.type !== 'all' && entry.type !== query.type) {
return false;
}
// Tags filter
if (query.tags && query.tags.length > 0) {
const entryTags = entry.tags || [];
const hasMatchingTag = query.tags.some((tag) => entryTags.includes(tag));
if (!hasMatchingTag) {
return false;
}
}
// Author filter
if (query.author && entry.author !== query.author) {
return false;
}
// Deprecated filter
if (query.deprecated !== undefined && entry.deprecated !== query.deprecated) {
return false;
}
// Version range filter
if (query.versionRange) {
try {
if (!this.versionManager.satisfiesRange(entry.version, query.versionRange)) {
return false;
}
}
catch (error) {
// If version range is invalid, skip this filter
}
}
// Search text filter
if (query.searchText) {
const searchText = query.searchText.toLowerCase();
const matchesName = entry.name.toLowerCase().includes(searchText);
const matchesDescription = entry.description.toLowerCase().includes(searchText);
const matchesTags = entry.tags?.some((tag) => tag.toLowerCase().includes(searchText)) || false;
if (!matchesName && !matchesDescription && !matchesTags) {
return false;
}
}
return true;
});
}
applySorting(entries, query) {
const sortBy = query.sortBy || 'name';
const sortOrder = query.sortOrder || 'asc';
return entries.sort((a, b) => {
let comparison = 0;
switch (sortBy) {
case 'name':
comparison = a.name.localeCompare(b.name);
break;
case 'version':
comparison = this.versionManager.compareVersions(a.version, b.version);
break;
case 'created':
comparison = a.createdAt.getTime() - b.createdAt.getTime();
break;
case 'updated':
comparison = a.updatedAt.getTime() - b.updatedAt.getTime();
break;
default:
comparison = a.name.localeCompare(b.name);
}
return sortOrder === 'desc' ? -comparison : comparison;
});
}
convertToDiscoveryEntries(entries) {
return entries.map((entry) => {
const discoveryEntry = {
name: entry.name,
type: entry.type,
description: entry.description,
version: this.versionManager.formatVersion(entry.version),
deprecated: entry.deprecated || false,
tags: entry.tags || [],
};
if (entry.type === 'tool') {
discoveryEntry.inputSchema = entry.toolDefinition.inputSchema;
}
else {
discoveryEntry.parameters = entry.promptDefinition.parameters;
}
return discoveryEntry;
});
}
generateDiscoveryMetadata(toolEntries, promptEntries, query) {
const allEntries = [
...Array.from(toolEntries.values()),
...Array.from(promptEntries.values()),
];
const categories = new Set();
let latestVersion = { major: 0, minor: 0, patch: 0 };
allEntries.forEach((entry) => {
entry.tags?.forEach((tag) => categories.add(tag));
if (this.versionManager.compareVersions(entry.version, latestVersion) > 0) {
latestVersion = entry.version;
}
});
return {
totalTools: toolEntries.size,
totalPrompts: promptEntries.size,
categories: Array.from(categories),
latestVersion: this.versionManager.formatVersion(latestVersion),
serverCapabilities: [
'tools',
'prompts',
'versioning',
'discovery',
'search',
'filtering',
'pagination',
'sorting',
],
};
}
}
//# sourceMappingURL=DiscoveryService.js.map