11import { type CallToolResult } from '@modelcontextprotocol/sdk/types.js'
22import { z } from 'zod'
33
4- import {
5- handleKVNamespaceCreate ,
6- handleKVNamespaceDelete ,
7- handleKVNamespaceGet ,
8- handleKVNamespacesList ,
9- handleKVNamespaceUpdate ,
10- } from '../api/kv'
114import { getCloudflareClient } from '../cloudflare-api'
125import { type CloudflareMcpAgent } from '../types/cloudflare-mcp-agent'
6+ import {
7+ KvNamespaceIdSchema ,
8+ KvNamespacesListParamsSchema ,
9+ KvNamespaceTitleSchema ,
10+ } from '../types/kv_namespace'
1311
14- const kvNamespaceTitle = z . string ( ) . describe ( 'The title of the kv namespace' )
15- const kvNamespaceId = z . string ( ) . describe ( 'The id of the kv namespace' )
12+ // Define the standard response for missing account ID
1613const MISSING_ACCOUNT_ID_RESPONSE = {
1714 content : [
1815 {
@@ -23,21 +20,27 @@ const MISSING_ACCOUNT_ID_RESPONSE = {
2320} satisfies CallToolResult
2421
2522export function registerKVTools ( agent : CloudflareMcpAgent ) {
23+ /**
24+ * Tool to list KV namespaces.
25+ */
2626 agent . server . tool (
2727 'kv_namespaces_list' ,
2828 'List all of the kv namespaces in your Cloudflare account' ,
29- { } ,
30- async ( ) => {
29+ { params : KvNamespacesListParamsSchema . optional ( ) } ,
30+ async ( { params } ) => {
3131 const account_id = agent . getActiveAccountId ( )
3232 if ( ! account_id ) {
3333 return MISSING_ACCOUNT_ID_RESPONSE
3434 }
3535 try {
36- const namespaces = await handleKVNamespacesList ( {
37- client : getCloudflareClient ( agent . props . accessToken ) ,
36+ const client = getCloudflareClient ( agent . props . accessToken )
37+ const response = await client . kv . namespaces . list ( {
3838 account_id,
39+ ...params ,
3940 } )
4041
42+ const namespaces = response . result ?? [ ]
43+
4144 return {
4245 content : [
4346 {
@@ -54,29 +57,31 @@ export function registerKVTools(agent: CloudflareMcpAgent) {
5457 content : [
5558 {
5659 type : 'text' ,
57- text : `Error listing KV namespaces: ${ error instanceof Error && error . message } ` ,
60+ text : `Error listing KV namespaces: ${ error instanceof Error ? error . message : String ( error ) } ` ,
5861 } ,
5962 ] ,
6063 }
6164 }
6265 }
6366 )
6467
68+ /**
69+ * Tool to create a KV namespace.
70+ */
6571 agent . server . tool (
6672 'kv_namespace_create' ,
6773 'Create a new kv namespace in your Cloudflare account' ,
68- { title : kvNamespaceTitle } ,
74+ {
75+ title : KvNamespaceTitleSchema ,
76+ } ,
6977 async ( { title } ) => {
7078 const account_id = agent . getActiveAccountId ( )
7179 if ( ! account_id ) {
7280 return MISSING_ACCOUNT_ID_RESPONSE
7381 }
7482 try {
75- const namespace = await handleKVNamespaceCreate ( {
76- client : getCloudflareClient ( agent . props . accessToken ) ,
77- account_id,
78- title : title ,
79- } )
83+ const client = getCloudflareClient ( agent . props . accessToken )
84+ const namespace = await client . kv . namespaces . create ( { account_id, title } )
8085 return {
8186 content : [
8287 {
@@ -90,34 +95,36 @@ export function registerKVTools(agent: CloudflareMcpAgent) {
9095 content : [
9196 {
9297 type : 'text' ,
93- text : `Error creating KV namespace: ${ error instanceof Error && error . message } ` ,
98+ text : `Error creating KV namespace: ${ error instanceof Error ? error . message : String ( error ) } ` ,
9499 } ,
95100 ] ,
96101 }
97102 }
98103 }
99104 )
100105
106+ /**
107+ * Tool to delete a KV namespace.
108+ */
101109 agent . server . tool (
102110 'kv_namespace_delete' ,
103111 'Delete a kv namespace in your Cloudflare account' ,
104- { namespace_id : kvNamespaceId } ,
112+ {
113+ namespace_id : KvNamespaceIdSchema ,
114+ } ,
105115 async ( { namespace_id } ) => {
106116 const account_id = agent . getActiveAccountId ( )
107117 if ( ! account_id ) {
108118 return MISSING_ACCOUNT_ID_RESPONSE
109119 }
110120 try {
111- const namespace = await handleKVNamespaceDelete ( {
112- client : getCloudflareClient ( agent . props . accessToken ) ,
113- account_id,
114- namespace_id,
115- } )
121+ const client = getCloudflareClient ( agent . props . accessToken )
122+ const result = await client . kv . namespaces . delete ( namespace_id , { account_id } )
116123 return {
117124 content : [
118125 {
119126 type : 'text' ,
120- text : JSON . stringify ( namespace ) ,
127+ text : JSON . stringify ( result ?? { success : true } ) ,
121128 } ,
122129 ] ,
123130 }
@@ -126,29 +133,31 @@ export function registerKVTools(agent: CloudflareMcpAgent) {
126133 content : [
127134 {
128135 type : 'text' ,
129- text : `Error deleting KV namespace: ${ error instanceof Error && error . message } ` ,
136+ text : `Error deleting KV namespace: ${ error instanceof Error ? error . message : String ( error ) } ` ,
130137 } ,
131138 ] ,
132139 }
133140 }
134141 }
135142 )
136143
144+ /**
145+ * Tool to get details of a specific KV namespace.
146+ */
137147 agent . server . tool (
138148 'kv_namespace_get' ,
139- 'Get a kv namespace in your Cloudflare account' ,
140- { namespace_id : kvNamespaceId } ,
149+ 'Get details of a kv namespace in your Cloudflare account' ,
150+ {
151+ namespace_id : KvNamespaceIdSchema ,
152+ } ,
141153 async ( { namespace_id } ) => {
142154 const account_id = agent . getActiveAccountId ( )
143155 if ( ! account_id ) {
144156 return MISSING_ACCOUNT_ID_RESPONSE
145157 }
146158 try {
147- const namespace = await handleKVNamespaceGet ( {
148- client : getCloudflareClient ( agent . props . accessToken ) ,
149- account_id,
150- namespace_id,
151- } )
159+ const client = getCloudflareClient ( agent . props . accessToken )
160+ const namespace = await client . kv . namespaces . get ( namespace_id , { account_id } )
152161 return {
153162 content : [
154163 {
@@ -162,38 +171,40 @@ export function registerKVTools(agent: CloudflareMcpAgent) {
162171 content : [
163172 {
164173 type : 'text' ,
165- text : `Error getting KV namespace: ${ error instanceof Error && error . message } ` ,
174+ text : `Error getting KV namespace: ${ error instanceof Error ? error . message : String ( error ) } ` ,
166175 } ,
167176 ] ,
168177 }
169178 }
170179 }
171180 )
172181
182+ /**
183+ * Tool to update the title of a KV namespace.
184+ */
173185 agent . server . tool (
174186 'kv_namespace_update' ,
175- 'Update a kv namespace in your Cloudflare account' ,
187+ 'Update the title of a kv namespace in your Cloudflare account' ,
176188 {
177- namespace_id : kvNamespaceId ,
178- title : kvNamespaceTitle ,
189+ namespace_id : KvNamespaceIdSchema ,
190+ title : KvNamespaceTitleSchema ,
179191 } ,
180192 async ( { namespace_id, title } ) => {
181193 const account_id = agent . getActiveAccountId ( )
182194 if ( ! account_id ) {
183195 return MISSING_ACCOUNT_ID_RESPONSE
184196 }
185197 try {
186- const namespaceUpdateResponse = await handleKVNamespaceUpdate ( {
187- client : getCloudflareClient ( agent . props . accessToken ) ,
198+ const client = getCloudflareClient ( agent . props . accessToken )
199+ const result = await client . kv . namespaces . update ( namespace_id , {
188200 account_id,
189- namespace_id,
190201 title,
191202 } )
192203 return {
193204 content : [
194205 {
195206 type : 'text' ,
196- text : JSON . stringify ( namespaceUpdateResponse ) ,
207+ text : JSON . stringify ( result ?? { success : true } ) ,
197208 } ,
198209 ] ,
199210 }
@@ -202,7 +213,7 @@ export function registerKVTools(agent: CloudflareMcpAgent) {
202213 content : [
203214 {
204215 type : 'text' ,
205- text : `Error updating KV namespace: ${ error instanceof Error && error . message } ` ,
216+ text : `Error updating KV namespace: ${ error instanceof Error ? error . message : String ( error ) } ` ,
206217 } ,
207218 ] ,
208219 }
0 commit comments