diff --git a/mcp.go b/mcp.go
index f664d9b..d8c45fa 100644
--- a/mcp.go
+++ b/mcp.go
@@ -28,25 +28,13 @@ var mcpServer = &cli.Command{
 
 		s.AddTool(mcp.NewTool("publish_note",
 			mcp.WithDescription("Publish a short note event to Nostr with the given text content"),
-			mcp.WithString("relay",
-				mcp.Description("Relay to publish the note to"),
-			),
-			mcp.WithString("content",
-				mcp.Required(),
-				mcp.Description("Arbitrary string to be published"),
-			),
-			mcp.WithString("mention",
-				mcp.Required(),
-				mcp.Description("Nostr user's public key to be mentioned"),
-			),
-		), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
-			content, _ := request.Params.Arguments["content"].(string)
-			mention, _ := request.Params.Arguments["mention"].(string)
-			relayI, ok := request.Params.Arguments["relay"]
-			var relay string
-			if ok {
-				relay, _ = relayI.(string)
-			}
+			mcp.WithString("content", mcp.Description("Arbitrary string to be published"), mcp.Required()),
+			mcp.WithString("relay", mcp.Description("Relay to publish the note to")),
+			mcp.WithString("mention", mcp.Description("Nostr user's public key to be mentioned")),
+		), func(ctx context.Context, r mcp.CallToolRequest) (*mcp.CallToolResult, error) {
+			content := required[string](r, "content")
+			mention, _ := optional[string](r, "mention")
+			relay, _ := optional[string](r, "relay")
 
 			if mention != "" && !nostr.IsValidPublicKey(mention) {
 				return mcp.NewToolResultError("the given mention isn't a valid public key, it must be 32 bytes hex, like the ones returned by search_profile"), nil
@@ -81,7 +69,9 @@ var mcpServer = &cli.Command{
 			}
 
 			// extra relay specified
-			relays = append(relays, relay)
+			if relay != "" {
+				relays = append(relays, relay)
+			}
 
 			result := strings.Builder{}
 			result.WriteString(
@@ -111,12 +101,9 @@ var mcpServer = &cli.Command{
 
 		s.AddTool(mcp.NewTool("resolve_nostr_uri",
 			mcp.WithDescription("Resolve URIs prefixed with nostr:, including nostr:nevent1..., nostr:npub1..., nostr:nprofile1... and nostr:naddr1..."),
-			mcp.WithString("uri",
-				mcp.Required(),
-				mcp.Description("URI to be resolved"),
-			),
-		), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
-			uri, _ := request.Params.Arguments["uri"].(string)
+			mcp.WithString("uri", mcp.Description("URI to be resolved"), mcp.Required()),
+		), func(ctx context.Context, r mcp.CallToolRequest) (*mcp.CallToolResult, error) {
+			uri := required[string](r, "uri")
 			if strings.HasPrefix(uri, "nostr:") {
 				uri = uri[6:]
 			}
@@ -159,12 +146,9 @@ var mcpServer = &cli.Command{
 
 		s.AddTool(mcp.NewTool("search_profile",
 			mcp.WithDescription("Search for the public key of a Nostr user given their name"),
-			mcp.WithString("name",
-				mcp.Required(),
-				mcp.Description("Name to be searched"),
-			),
-		), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
-			name, _ := request.Params.Arguments["name"].(string)
+			mcp.WithString("name", mcp.Description("Name to be searched"), mcp.Required()),
+		), func(ctx context.Context, r mcp.CallToolRequest) (*mcp.CallToolResult, error) {
+			name := required[string](r, "name")
 			re := sys.Pool.QuerySingle(ctx, []string{"relay.nostr.band", "nostr.wine"}, nostr.Filter{Search: name, Kinds: []int{0}})
 			if re == nil {
 				return mcp.NewToolResultError("couldn't find anyone with that name"), nil
@@ -175,42 +159,24 @@ var mcpServer = &cli.Command{
 
 		s.AddTool(mcp.NewTool("get_outbox_relay_for_pubkey",
 			mcp.WithDescription("Get the best relay from where to read notes from a specific Nostr user"),
-			mcp.WithString("pubkey",
-				mcp.Required(),
-				mcp.Description("Public key of Nostr user we want to know the relay from where to read"),
-			),
-		), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
-			pubkey, _ := request.Params.Arguments["pubkey"].(string)
+			mcp.WithString("pubkey", mcp.Description("Public key of Nostr user we want to know the relay from where to read"), mcp.Required()),
+		), func(ctx context.Context, r mcp.CallToolRequest) (*mcp.CallToolResult, error) {
+			pubkey := required[string](r, "pubkey")
 			res := sys.FetchOutboxRelays(ctx, pubkey, 1)
 			return mcp.NewToolResultText(res[0]), nil
 		})
 
 		s.AddTool(mcp.NewTool("read_events_from_relay",
 			mcp.WithDescription("Makes a REQ query to one relay using the specified parameters, this can be used to fetch notes from a profile"),
-			mcp.WithNumber("kind",
-				mcp.Required(),
-				mcp.Description("event kind number to include in the 'kinds' field"),
-			),
-			mcp.WithString("pubkey",
-				mcp.Description("pubkey to include in the 'authors' field"),
-			),
-			mcp.WithNumber("limit",
-				mcp.Required(),
-				mcp.Description("maximum number of events to query"),
-			),
-			mcp.WithString("relay",
-				mcp.Required(),
-				mcp.Description("relay URL to send the query to"),
-			),
-		), func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
-			relay, _ := request.Params.Arguments["relay"].(string)
-			limit, _ := request.Params.Arguments["limit"].(int)
-			kind, _ := request.Params.Arguments["kind"].(int)
-			pubkeyI, ok := request.Params.Arguments["pubkey"]
-			var pubkey string
-			if ok {
-				pubkey, _ = pubkeyI.(string)
-			}
+			mcp.WithString("relay", mcp.Description("relay URL to send the query to"), mcp.Required()),
+			mcp.WithNumber("kind", mcp.Description("event kind number to include in the 'kinds' field"), mcp.Required()),
+			mcp.WithNumber("limit", mcp.Description("maximum number of events to query"), mcp.Required()),
+			mcp.WithString("pubkey", mcp.Description("pubkey to include in the 'authors' field")),
+		), func(ctx context.Context, r mcp.CallToolRequest) (*mcp.CallToolResult, error) {
+			relay := required[string](r, "relay")
+			kind := int(required[float64](r, "kind"))
+			limit := int(required[float64](r, "limit"))
+			pubkey, _ := optional[string](r, "pubkey")
 
 			if pubkey != "" && !nostr.IsValidPublicKey(pubkey) {
 				return mcp.NewToolResultError("the given pubkey isn't a valid public key, it must be 32 bytes hex, like the ones returned by search_profile"), nil
@@ -242,3 +208,28 @@ var mcpServer = &cli.Command{
 		return server.ServeStdio(s)
 	},
 }
+
+func required[T comparable](r mcp.CallToolRequest, p string) T {
+	var zero T
+	if _, ok := r.Params.Arguments[p]; !ok {
+		return zero
+	}
+	if _, ok := r.Params.Arguments[p].(T); !ok {
+		return zero
+	}
+	if r.Params.Arguments[p].(T) == zero {
+		return zero
+	}
+	return r.Params.Arguments[p].(T)
+}
+
+func optional[T any](r mcp.CallToolRequest, p string) (T, bool) {
+	var zero T
+	if _, ok := r.Params.Arguments[p]; !ok {
+		return zero, false
+	}
+	if _, ok := r.Params.Arguments[p].(T); !ok {
+		return zero, false
+	}
+	return r.Params.Arguments[p].(T), true
+}