Skip to main content
Glama

MCP-NOSTR

by pablof7z
instructions.ts4.98 kB
import { NDKEvent, type NDKFilter, type NDKKind } from "@nostr-dev-kit/ndk"; import { ndk } from "../../ndk.js"; export { NDKEvent, ndk }; import { log } from "../utils/log.js"; import fs from 'fs'; // Define the instruction kind export const INSTRUCTION_KIND = 1339 as NDKKind; /** * Fetch an instruction by its event ID * @param eventId The Nostr event ID * @returns The instruction event or null if not found */ export async function fetchInstructionById(eventId: string): Promise<NDKEvent | null> { const filter: NDKFilter = { kinds: [INSTRUCTION_KIND], ids: [eventId], }; log(`Fetching instruction with ID: ${eventId}`); const events = await ndk.fetchEvents(filter); if (events.size === 0) { return null; } const eventArray = Array.from(events); return eventArray[0] as NDKEvent; } /** * Find existing instructions by title and pubkey * @param title Instruction title to search for * @param pubkey Pubkey of the author * @returns Array of matching instruction events */ export async function findExistingInstructions(title: string, pubkey: string): Promise<NDKEvent[]> { const filter: NDKFilter = { kinds: [INSTRUCTION_KIND], authors: [pubkey], }; log(`Looking for existing instructions with title "${title}" from pubkey ${pubkey}`); const events = await ndk.fetchEvents(filter); log(`Found ${events.size} existing instructions`); return Array.from(events); } /** * Get version number from instruction event * @param event The instruction event * @returns Version number as string, or "1" if not found */ export function getVersion(event: NDKEvent): string { return event.tags.find(tag => tag[0] === "ver")?.[1] || "1"; } /** * Find instructions matching a query * @param query The search query * @param limit Maximum number of results to return * @returns Array of matching instruction events */ export async function findInstructions(query: string, limit: number = 50): Promise<NDKEvent[]> { const filter: NDKFilter = { kinds: [INSTRUCTION_KIND], limit, }; const regexp = new RegExp(query, 'i'); log(`Searching for instructions matching: ${query}`); const events = await ndk.fetchEvents(filter); // Filter events based on the query return Array.from(events).filter(event => { // Search in title, description, and tags const title = getTagValue(event, 'title') || ''; const description = getTagValue(event, 'description') || ''; const tags = event.tags.filter(tag => tag[0] === 't').map(tag => tag[1]); // Case-insensitive search const lowerQuery = query.toLowerCase(); return ( title.toLowerCase().includes(lowerQuery) || description.toLowerCase().includes(lowerQuery) || tags.some(tag => tag?.toLowerCase().includes(lowerQuery)) || event.content.match(regexp) ); }); } /** * Get the tag value from an event * @param event The Nostr event * @param tagName The tag name to find * @param defaultValue Optional default value if tag not found * @returns The tag value or default value */ export function getTagValue(event: NDKEvent, tagName: string, defaultValue: string = ''): string { return event.tags.find((tag: string[]) => tag[0] === tagName)?.[1] || defaultValue; } /** * Format instruction events for display * @param instructions Array of instruction events * @returns Formatted string representation of instructions */ export function formatInstructions(instructions: NDKEvent[]): string { if (instructions.length === 0) { return "No instructions found."; } return instructions.map((instruction, index) => { const title = getTagValue(instruction, 'title'); const description = getTagValue(instruction, 'description'); const version = getVersion(instruction); return `${index + 1}. ${title} (v${version}): ${description}`; }).join('\n'); } /** * Publish an instruction to Nostr * @param content The instruction content * @param title The instruction title * @param description The instruction description * @param tags The instruction tags * @returns The published event */ export async function publishInstruction( content: string, title: string, description: string, tags: string[] ): Promise<NDKEvent> { const event = new NDKEvent(ndk); event.kind = INSTRUCTION_KIND; // Determine version number let version = "1"; try { const existingEvents = await findExistingInstructions(title, ndk.signer?.pubkey || ""); if (existingEvents.length > 0) { const versions = existingEvents.map(getVersion).map(v => parseInt(v, 10)); version = (Math.max(...versions) + 1).toString(); } } catch (error) { log(`Error checking for existing versions: ${error}`); } // Add standard tags event.tags = [ ['title', title], ['description', description], ['ver', version], ...tags.map(tag => ['t', tag]) ]; event.content = content; await event.publish(); return event; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pablof7z/mcp-code'

If you have feedback or need assistance with the MCP directory API, please join our Discord server