Skip to main content
Glama

postNote

Sign and publish a note to the Nostr social network using a private key. Include optional tags and relays for targeted distribution.

Instructions

Post a note using an existing private key (authenticated posting)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contentYesContent of the note to post
privateKeyYesPrivate key to sign the note with (hex format or nsec format)
relaysNoOptional list of relays to publish to
tagsNoOptional tags to include with the note

Implementation Reference

  • The core handler function for the postNote tool. It normalizes the private key, derives the public key, creates a kind 1 note event, signs it, and publishes it to the specified Nostr relays.
    export async function postNote( privateKey: string, content: string, tags: string[][] = [], relays: string[] = DEFAULT_RELAYS ): Promise<{ success: boolean, message: string, noteId?: string, publicKey?: string }> { try { // console.log(`Preparing to post authenticated note to ${relays.join(", ")}`); // Normalize private key const normalizedPrivateKey = normalizePrivateKey(privateKey); // Derive public key from private key const publicKey = getPublicKeyFromPrivate(normalizedPrivateKey); // Create a fresh pool for this request const pool = getFreshPool(relays); try { // Create the note event template const noteTemplate = createEvent({ kind: 1, // kind 1 is a text note content, tags }, publicKey); // Get event hash and sign it const eventId = await getEventHash(noteTemplate); const signature = await signEvent(eventId, normalizedPrivateKey); // Create complete signed event const signedNote = { ...noteTemplate, id: eventId, sig: signature }; // If no relays specified, just return success with event creation if (relays.length === 0) { return { success: true, message: 'Note created and signed successfully (no relays specified for publishing)', noteId: signedNote.id, publicKey: publicKey, }; } // Publish to relays - pool.publish returns array of promises const pubPromises = pool.publish(relays, signedNote); // Wait for all publish attempts to complete or timeout const results = await Promise.allSettled(pubPromises); // Check if at least one relay accepted the note const successCount = results.filter(r => r.status === 'fulfilled' && r.value?.success === true ).length; if (successCount === 0) { return { success: false, message: 'Failed to publish note to any relay', }; } return { success: true, message: `Note published to ${successCount}/${relays.length} relays`, noteId: signedNote.id, publicKey: publicKey, }; } catch (error) { console.error("Error posting note:", error); return { success: false, message: `Error posting note: ${error instanceof Error ? error.message : "Unknown error"}`, }; } finally { // Clean up any subscriptions and close the pool await pool.close(); } } catch (error) { return { success: false, message: `Fatal error: ${error instanceof Error ? error.message : "Unknown error"}`, }; } }
  • Zod schema defining the input parameters and validation for the postNote tool.
    export const postNoteToolConfig = { privateKey: z.string().describe("Private key to sign the note with (hex format or nsec format)"), content: z.string().describe("Content of the note to post"), tags: z.array(z.array(z.string())).optional().describe("Optional tags to include with the note"), relays: z.array(z.string()).optional().describe("Optional list of relays to publish to"), };
  • index.ts:1346-1402 (registration)
    MCP server registration of the postNote tool, which wraps the handler function and formats the response for the MCP protocol.
    server.tool( "postNote", "Post a note using an existing private key (authenticated posting)", postNoteToolConfig, async ({ privateKey, content, tags, relays }) => { try { const result = await postNote(privateKey, content, tags, relays); if (result.success) { let response = `Note posted successfully!\n\n`; response += `${result.message}\n`; if (result.noteId) { response += `Note ID: ${result.noteId}\n`; } if (result.publicKey) { response += `Author: ${formatPubkey(result.publicKey)}\n`; } response += `Content: "${content}"\n`; if (tags && tags.length > 0) { response += `Tags: ${JSON.stringify(tags)}\n`; } if (relays && relays.length > 0) { response += `Relays: ${relays.join(", ")}\n`; } return { content: [ { type: "text", text: response, }, ], }; } else { return { content: [ { type: "text", text: `Failed to post note: ${result.message}`, }, ], }; } } catch (error) { console.error("Error in postNote tool:", error); return { content: [ { type: "text", text: `Error posting note: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], }; } }, );

Other Tools

Related Tools

Latest Blog Posts

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/AustinKelsay/nostr-mcp-server'

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