createProfile
Create a new Nostr profile with display name, bio, picture, and other metadata to establish identity on the decentralized social network.
Instructions
Create a new Nostr profile (kind 0)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Display name | |
| about | No | Bio / about text | |
| picture | No | Profile picture URL | |
| nip05 | No | NIP-05 identifier | |
| lud16 | No | Lightning address | |
| banner | No | Banner image URL | |
| website | No | Website URL | |
| privateKey | No | Private key (nsec or hex). Optional when NOSTR_BUNKER_URI is configured. | |
| relays | No | Relays to publish to |
Implementation Reference
- src/tools/profile-tools.ts:55-58 (handler)The main handler function for creating a Nostr profile.
export async function createProfile(params: z.infer<typeof createProfileSchema>) { const { privateKey, relays, ...fields } = params; return buildAndPublishProfile(fields, privateKey, relays); } - src/tools/profile-tools.ts:11-21 (schema)Zod schema defining the input parameters for creating a profile.
export const createProfileSchema = z.object({ name: z.string().optional().describe('Display name'), about: z.string().optional().describe('Bio / about text'), picture: z.string().optional().describe('Profile picture URL'), nip05: z.string().optional().describe('NIP-05 identifier'), lud16: z.string().optional().describe('Lightning address'), banner: z.string().optional().describe('Banner image URL'), website: z.string().optional().describe('Website URL'), privateKey: z.string().optional().describe(privateKeyDesc), relays: z.array(z.string()).optional().describe('Relays to publish to'), }); - src/index.ts:89-91 (registration)Registration of the createProfile MCP tool.
server.tool('createProfile', 'Create a new Nostr profile (kind 0)', createProfileSchema.shape, async (params) => { return textResult(await createProfile(params)); }); - src/tools/profile-tools.ts:25-53 (helper)Helper function that constructs and publishes the Nostr metadata event.
async function buildAndPublishProfile( fields: Record<string, string | undefined>, privateKey: string | undefined, relays: string[] | undefined, ): Promise<{ event: VerifiedEvent; published: { successes: string[]; failures: string[] } }> { const content: Record<string, string> = {}; for (const [k, v] of Object.entries(fields)) { if (v !== undefined) content[k] = v; } const template: EventTemplate = { kind: KINDS.METADATA, content: JSON.stringify(content), tags: [], created_at: Math.floor(Date.now() / 1000), }; let signed: VerifiedEvent; if (isBunkerMode()) { signed = await signEventWithBunker(template); } else { if (!privateKey) throw new Error('privateKey is required when NOSTR_BUNKER_URI is not configured'); const sk = normalizePrivateKey(privateKey); signed = finalizeEvent(template, sk); } const result = await publishEvent(signed, relays ?? DEFAULT_RELAYS); return { event: signed, published: result }; }