Skip to content

Commit f7390a0

Browse files
authored
fix: Tool Input Array JSON Schema Validation (#31)
We don't provide the item schema in array types. It fails when using OpenAI and Gemini models
1 parent 34949be commit f7390a0

11 files changed

+112
-2
lines changed

pkg/mcp/kafka_admin_topics_tools.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ func KafkaAdminAddTopicTools(s *server.MCPServer, readOnly bool, features []stri
113113
"Each entry should be in the format 'key=value'. "+
114114
"Example configs include 'cleanup.policy', 'retention.ms', 'compression.type'. "+
115115
"Optional."),
116+
mcp.Items(
117+
map[string]interface{}{
118+
"type": "string",
119+
"description": "config entry",
120+
},
121+
),
116122
),
117123
)
118124
s.AddTool(kafkaTopicTool, handleKafkaTopicTool(readOnly))

pkg/mcp/kafka_client_produce_tools.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ func KafkaClientAddProduceTools(s *server.MCPServer, readOnly bool, features []s
9393
mcp.Description("Message headers in the format of [{\"key\": \"value\"}]. "+
9494
"Optional. Headers allow you to attach metadata to messages without modifying the payload. "+
9595
"They are passed along with the message to consumers."),
96+
mcp.Items(
97+
map[string]interface{}{
98+
"type": "string",
99+
"description": "header entry",
100+
},
101+
),
96102
),
97103
mcp.WithBoolean("sync",
98104
mcp.Description("Whether to wait for server acknowledgment before returning. "+

pkg/mcp/pulsar_admin_cluster_tools.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,21 @@ func PulsarAdminAddClusterTools(s *server.MCPServer, readOnly bool, features []s
8484
mcp.Description("List of clusters to be registered as peer-clusters, used when:\n"+
8585
"- resource=cluster and operation is create or update\n"+
8686
"- resource=peer_clusters and operation is update"),
87+
mcp.Items(
88+
map[string]interface{}{
89+
"type": "string",
90+
"description": "peer cluster name",
91+
},
92+
),
8793
),
8894
mcp.WithArray("brokers",
8995
mcp.Description("List of broker names to include in a failure domain, required when resource=failure_domain and operation is create or update"),
96+
mcp.Items(
97+
map[string]interface{}{
98+
"type": "string",
99+
"description": "broker",
100+
},
101+
),
90102
),
91103
)
92104
s.AddTool(clusterTool, handleClusterTool(readOnly))

pkg/mcp/pulsar_admin_functions_tools.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,14 @@ func PulsarAdminAddFunctionsTools(s *server.MCPServer, readOnly bool, features [
9090
mcp.Description("The input topics for the function (array of strings). Optional for 'create' and 'update' operations. "+
9191
"Topics must be specified in the format 'persistent://tenant/namespace/topic'. "+
9292
"Functions can consume from multiple topics, each with potentially different serialization types. "+
93-
"All input topics should exist before the function is created.")),
93+
"All input topics should exist before the function is created."),
94+
mcp.Items(
95+
map[string]interface{}{
96+
"type": "string",
97+
"description": "input topic",
98+
},
99+
),
100+
),
94101
mcp.WithString("output",
95102
mcp.Description("The output topic for the function results. Optional for 'create' and 'update' operations. "+
96103
"Specified in the format 'persistent://tenant/namespace/topic'. "+

pkg/mcp/pulsar_admin_namespace_policy_tools.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,30 @@ func PulsarAdminAddNamespacePolicyTools(s *server.MCPServer, readOnly bool, feat
172172
),
173173
mcp.WithArray("actions",
174174
mcp.Description("Actions to grant for permission policies (e.g., produce, consume)"),
175+
mcp.Items(
176+
map[string]interface{}{
177+
"type": "string",
178+
"description": "action",
179+
},
180+
),
175181
),
176182
mcp.WithArray("clusters",
177183
mcp.Description("List of clusters for replication policies"),
184+
mcp.Items(
185+
map[string]interface{}{
186+
"type": "string",
187+
"description": "cluster",
188+
},
189+
),
178190
),
179191
mcp.WithArray("roles",
180192
mcp.Description("List of roles for subscription permission policies"),
193+
mcp.Items(
194+
map[string]interface{}{
195+
"type": "string",
196+
"description": "role",
197+
},
198+
),
181199
),
182200
mcp.WithString("ttl",
183201
mcp.Description("Message TTL in seconds (or 0 to disable TTL)"),

pkg/mcp/pulsar_admin_namespace_tools.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ func PulsarAdminAddNamespaceTools(s *server.MCPServer, readOnly bool, features [
6464
),
6565
mcp.WithArray("clusters",
6666
mcp.Description("List of clusters to assign when creating a namespace. Used with 'create' operation."),
67+
mcp.Items(
68+
map[string]interface{}{
69+
"type": "string",
70+
"description": "Cluster name",
71+
},
72+
),
6773
),
6874
mcp.WithString("subscription",
6975
mcp.Description("Subscription name. Required for 'unsubscribe' operation, optional for 'clear_backlog'."),

pkg/mcp/pulsar_admin_nsisolationpolicy_tools.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,30 @@ func PulsarAdminAddNsIsolationPolicyTools(s *server.MCPServer, readOnly bool, fe
7070
),
7171
mcp.WithArray("namespaces",
7272
mcp.Description("List of namespaces to apply the isolation policy. Required for policy.set"),
73+
mcp.Items(
74+
map[string]interface{}{
75+
"type": "string",
76+
"description": "namespace",
77+
},
78+
),
7379
),
7480
mcp.WithArray("primary",
7581
mcp.Description("List of primary brokers for the namespaces. Required for policy.set"),
82+
mcp.Items(
83+
map[string]interface{}{
84+
"type": "string",
85+
"description": "primary broker",
86+
},
87+
),
7688
),
7789
mcp.WithArray("secondary",
7890
mcp.Description("List of secondary brokers for the namespaces. Optional for policy.set"),
91+
mcp.Items(
92+
map[string]interface{}{
93+
"type": "string",
94+
"description": "secondary broker",
95+
},
96+
),
7997
),
8098
mcp.WithString("autoFailoverPolicyType",
8199
mcp.Description("Auto failover policy type (e.g., min_available). Optional for policy.set"),

pkg/mcp/pulsar_admin_sinks_tools.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,14 @@ func PulsarAdminAddSinksTools(s *server.MCPServer, readOnly bool, features []str
9494
"Topics must be specified in the format 'persistent://tenant/namespace/topic'. "+
9595
"Sinks can consume from multiple topics, but they should have compatible schemas. "+
9696
"All input topics should exist before the sink is created. "+
97-
"Either inputs or topics-pattern must be specified.")),
97+
"Either inputs or topics-pattern must be specified."),
98+
mcp.Items(
99+
map[string]interface{}{
100+
"type": "string",
101+
"description": "input topic",
102+
},
103+
),
104+
),
98105
mcp.WithString("topics-pattern",
99106
mcp.Description("TopicsPattern to consume from list of topics that match the pattern. Optional for 'create' and 'update' operations. "+
100107
"Specified as a regular expression, e.g., 'persistent://tenant/namespace/prefix.*'. "+

pkg/mcp/pulsar_admin_tenant_tools.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,24 @@ func PulsarAdminAddTenantTools(s *server.MCPServer, readOnly bool, features []st
7777
"namespaces within the tenant, and can manage topic configurations. "+
7878
"Format: array of role strings, e.g., ['admin1', 'orgAdmin']. "+
7979
"Use empty array [] to remove all admin roles."),
80+
mcp.Items(
81+
map[string]interface{}{
82+
"type": "string",
83+
"description": "role",
84+
},
85+
),
8086
),
8187
mcp.WithArray("allowedClusters",
8288
mcp.Description("List of clusters that this tenant can access. Required for 'create' and 'update' operations. "+
8389
"Restricts the tenant to only use specified clusters, enabling geographic or infrastructure isolation. "+
8490
"Format: array of cluster names, e.g., ['us-west', 'us-east']. "+
8591
"An empty list means no clusters are accessible to this tenant."),
92+
mcp.Items(
93+
map[string]interface{}{
94+
"type": "string",
95+
"description": "cluster",
96+
},
97+
),
8698
),
8799
)
88100
s.AddTool(tenantTool, handleTenantTool(readOnly))

pkg/mcp/pulsar_admin_topic_policy_tools.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ func PulsarAdminAddTopicPolicyTools(s *server.MCPServer, readOnly bool, features
178178
),
179179
mcp.WithArray("actions",
180180
mcp.Description("Actions to grant for permission policies. Valid values are: produce, consume"),
181+
mcp.Items(
182+
map[string]interface{}{
183+
"type": "string",
184+
"description": "action",
185+
},
186+
),
181187
),
182188
mcp.WithString("ttl",
183189
mcp.Description("Message TTL in seconds (or 0 to disable TTL)"),

0 commit comments

Comments
 (0)