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
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Content of the note to post | |
| privateKey | Yes | Private key to sign the note with (hex format or nsec format) | |
| relays | No | Optional list of relays to publish to | |
| tags | No | Optional tags to include with the note |
Implementation Reference
- profile/profile-tools.ts:246-334 (handler)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"}`, }; } }
- profile/profile-tools.ts:41-46 (schema)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"}`, }, ], }; } }, );