Skip to main content
Glama

updateProfile

Modify your Nostr profile by updating display name, bio, profile picture, NIP-05 identifier, Lightning address, LNURL, website, or relay list using a private key.

Instructions

Update an existing Nostr profile (kind 0 event)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
aboutNoAbout/bio text for the profile
lud06NoLNURL for receiving payments
lud16NoLightning address for receiving payments
nameNoDisplay name for the profile
nip05NoNIP-05 identifier (like email@domain.com)
pictureNoURL to profile picture
privateKeyYesPrivate key to sign the profile with (hex format or nsec format)
relaysNoOptional list of relays to publish to
websiteNoPersonal website URL

Implementation Reference

  • The core handler function that implements the updateProfile tool logic by delegating to createProfile, as Nostr profile updates work by publishing newer kind 0 metadata events.
    export async function updateProfile( privateKey: string, profileData: { name?: string; about?: string; picture?: string; nip05?: string; lud16?: string; lud06?: string; website?: string; }, relays: string[] = DEFAULT_RELAYS ): Promise<{ success: boolean, message: string, eventId?: string, publicKey?: string }> { // For kind 0 events (profiles), updating is the same as creating // The newest event replaces the older one return createProfile(privateKey, profileData, relays); }
  • Zod-based input schema configuration for the updateProfile tool parameters.
    // Schema for updateProfile tool export const updateProfileToolConfig = { privateKey: z.string().describe("Private key to sign the profile with (hex format or nsec format)"), name: z.string().optional().describe("Display name for the profile"), about: z.string().optional().describe("About/bio text for the profile"), picture: z.string().optional().describe("URL to profile picture"), nip05: z.string().optional().describe("NIP-05 identifier (like email@domain.com)"), lud16: z.string().optional().describe("Lightning address for receiving payments"), lud06: z.string().optional().describe("LNURL for receiving payments"), website: z.string().optional().describe("Personal website URL"), relays: z.array(z.string()).optional().describe("Optional list of relays to publish to"), };
  • index.ts:1275-1344 (registration)
    MCP server registration of the updateProfile tool, including the inline executor that calls the core updateProfile function and formats the MCP response.
    server.tool( "updateProfile", "Update an existing Nostr profile (kind 0 event)", updateProfileToolConfig, async ({ privateKey, name, about, picture, nip05, lud16, lud06, website, relays }) => { try { const profileData = { name, about, picture, nip05, lud16, lud06, website }; const result = await updateProfile(privateKey, profileData, relays); if (result.success) { let response = `Profile updated successfully!\n\n`; response += `${result.message}\n`; if (result.eventId) { response += `Event ID: ${result.eventId}\n`; } if (result.publicKey) { response += `Public Key: ${formatPubkey(result.publicKey)}\n`; } // Show the profile data that was updated response += "\nUpdated profile data:\n"; if (name) response += `Name: ${name}\n`; if (about) response += `About: ${about}\n`; if (picture) response += `Picture: ${picture}\n`; if (nip05) response += `NIP-05: ${nip05}\n`; if (lud16) response += `Lightning Address: ${lud16}\n`; if (lud06) response += `LNURL: ${lud06}\n`; if (website) response += `Website: ${website}\n`; return { content: [ { type: "text", text: response, }, ], }; } else { return { content: [ { type: "text", text: `Failed to update profile: ${result.message}`, }, ], }; } } catch (error) { console.error("Error in updateProfile tool:", error); return { content: [ { type: "text", text: `Error updating profile: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], }; } }, );
  • Supporting createProfile function that contains the actual profile event creation, signing, and publishing logic used by updateProfile.
    export async function createProfile( privateKey: string, profileData: { name?: string; about?: string; picture?: string; nip05?: string; lud16?: string; lud06?: string; website?: string; }, relays: string[] = DEFAULT_RELAYS ): Promise<{ success: boolean, message: string, eventId?: string, publicKey?: string }> { try { // Normalize private key const normalizedPrivateKey = normalizePrivateKey(privateKey); // Derive public key from private key const publicKey = getPublicKeyFromPrivate(normalizedPrivateKey); // Create profile metadata object const metadata: { name?: string; about?: string; picture?: string; nip05?: string; lud16?: string; lud06?: string; website?: string; } = {}; if (profileData.name) metadata.name = profileData.name; if (profileData.about) metadata.about = profileData.about; if (profileData.picture) metadata.picture = profileData.picture; if (profileData.nip05) metadata.nip05 = profileData.nip05; if (profileData.lud16) metadata.lud16 = profileData.lud16; if (profileData.lud06) metadata.lud06 = profileData.lud06; if (profileData.website) metadata.website = profileData.website; // Create a fresh pool for this request const pool = getFreshPool(relays); try { // Create the profile event template const profileTemplate = createEvent({ kind: 0, // kind 0 is profile metadata content: JSON.stringify(metadata), tags: [] }, publicKey); // Get event hash and sign it const eventId = await getEventHash(profileTemplate); const signature = await signEvent(eventId, normalizedPrivateKey); // Create complete signed event const signedProfile = { ...profileTemplate, id: eventId, sig: signature }; // If no relays specified, just return success with event creation if (relays.length === 0) { return { success: true, message: 'Profile event created successfully (no relays specified for publishing)', eventId: signedProfile.id, publicKey: publicKey, }; } // Publish to relays - pool.publish returns array of promises const pubPromises = pool.publish(relays, signedProfile); // Wait for all publish attempts to complete or timeout const results = await Promise.allSettled(pubPromises); // Check if at least one relay accepted the profile const successCount = results.filter(r => r.status === 'fulfilled' && r.value?.success === true ).length; if (successCount === 0) { return { success: false, message: 'Failed to publish profile to any relay', }; } return { success: true, message: `Profile published to ${successCount}/${relays.length} relays`, eventId: signedProfile.id, publicKey: publicKey, }; } catch (error) { console.error("Error creating profile:", error); return { success: false, message: `Error creating profile: ${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"}`, }; } }

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