Skip to main content
Glama
getId.ts5.11 kB
import { PrivateKey } from "@bsv/sdk"; import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js"; import type { CallToolResult, ServerNotification, ServerRequest, } from "@modelcontextprotocol/sdk/types.js"; import { z } from "zod"; import { BSOCIAL_API_URL } from "../constants"; import type { IdentityData, SigmaIdentityProfile } from "./types"; // Schema for bap_getId arguments export const bapGetIdArgsSchema = z.object({ idKey: z .string() .optional() .describe( "Optional Identity Key (Paymail or public key). If not provided, attempts to use the server's configured identity key.", ), }); export type BapGetIdArgs = z.infer<typeof bapGetIdArgsSchema>; /** * Fetches the identity profile from Sigma API. * @param idKey The identity key (Paymail or public key) to fetch the profile for. * @returns The identity data, or null if not found. */ export const fetchProfile = async ( idKey: string, ): Promise<IdentityData | null> => { const response = await fetch(`${BSOCIAL_API_URL}/identity/get`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ idKey }), }); if (!response.ok) { // For 404, Sigma API might return a specific body, but generally, we treat it as profile not found. if (response.status === 404) { return null; // Explicitly return null for 404 } const errorBody = await response.text(); throw new Error( `Sigma API request failed with status ${response.status}: ${errorBody}`, ); } try { const profileData = (await response.json()) as SigmaIdentityProfile; // Ensure result exists, even if it's null (which means not found) if (typeof profileData.result === "undefined") { throw new Error("Sigma API response is missing the 'result' field."); } return profileData.result; // This can be IdentityData or null } catch (jsonError) { // Handle cases where response is not JSON or structure is unexpected throw new Error( `Failed to parse Sigma API response: ${jsonError instanceof Error ? jsonError.message : String(jsonError)}`, ); } }; /** * Registers the bap_getId tool for fetching a BAP identity. */ export function registerBapGetIdTool( server: McpServer, identityPk?: PrivateKey, // Accept the global identityPk ) { server.tool( "bap_getId", "Retrieves a Bitcoin Attestation Protocol (BAP) identity profile using an idKey (Paymail or public key). If no idKey is provided, it attempts to use the server's configured identity key.", { args: bapGetIdArgsSchema }, async ( { args }: { args: BapGetIdArgs }, extra: RequestHandlerExtra<ServerRequest, ServerNotification>, ): Promise<CallToolResult> => { let targetIdKey = args.idKey; if (!targetIdKey) { // First priority: Use authenticated user's BAP ID from OAuth session const authInfo = (extra as any).authInfo; if (authInfo?.metadata?.bapId) { targetIdKey = authInfo.metadata.bapId; console.log(`Using authenticated user's BAP ID: ${targetIdKey}`); } // Second priority: Use authenticated user's pubkey else if (authInfo?.metadata?.pubkey) { targetIdKey = authInfo.metadata.pubkey; console.log(`Using authenticated user's pubkey: ${targetIdKey}`); } // Fallback: Attempt to get idKey from the passed identityPk or environment variable else { let pkToUse = identityPk; if (!pkToUse) { const identityKeyWifEnv = process.env.IDENTITY_KEY_WIF; if (identityKeyWifEnv) { try { pkToUse = PrivateKey.fromWif(identityKeyWifEnv); } catch (e) { // Don't error here, let it be handled by the final check } } } if (pkToUse) { // Sigma typically uses the public key string as the idKey targetIdKey = pkToUse.toPublicKey().toString(); } else { return { content: [ { type: "text", text: "idKey not provided and could not be derived from authenticated session or server configuration.", }, ], isError: true, }; } } } if (!targetIdKey) { return { content: [ { type: "text", text: "Critical error: targetIdKey is unexpectedly undefined after derivation attempts.", }, ], isError: true, }; } try { const identityDataResult = await fetchProfile(targetIdKey); if (identityDataResult === null) { return { content: [ { type: "text", text: `No BAP identity found for idKey: ${targetIdKey}`, }, ], isError: false, // Not an error, just no data found for the given key }; } return { content: [ { type: "text", text: JSON.stringify(identityDataResult, null, 2) }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error fetching BAP ID: ${errorMessage}` }, ], isError: true, }; } }, ); }

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/b-open-io/bsv-mcp'

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