@@ -63,10 +63,22 @@ export class MCPProxy {
6363 def . methods . forEach ( method => {
6464 const toolNameWithMethod = `${ toolName } -${ method . name } ` ;
6565 const truncatedToolName = this . truncateToolName ( toolNameWithMethod ) ;
66+
67+ // Look up the HTTP method to determine annotations
68+ const operation = this . openApiLookup [ toolNameWithMethod ] ;
69+ const httpMethod = operation ?. method ?. toLowerCase ( ) ;
70+ const isReadOnly = httpMethod === 'get' ;
71+
6672 tools . push ( {
6773 name : truncatedToolName ,
6874 description : method . description ,
6975 inputSchema : method . inputSchema as Tool [ 'inputSchema' ] ,
76+ annotations : {
77+ title : this . operationIdToTitle ( method . name ) ,
78+ ...( isReadOnly
79+ ? { readOnlyHint : true }
80+ : { destructiveHint : true } ) ,
81+ } ,
7082 } )
7183 } )
7284 } )
@@ -173,6 +185,19 @@ export class MCPProxy {
173185 return name . slice ( 0 , 64 ) ;
174186 }
175187
188+ /**
189+ * Convert an operationId like "createDatabase" to a human-readable title like "Create Database"
190+ */
191+ private operationIdToTitle ( operationId : string ) : string {
192+ // Split on camelCase boundaries and capitalize each word
193+ return operationId
194+ . replace ( / ( [ a - z ] ) ( [ A - Z ] ) / g, '$1 $2' )
195+ . replace ( / ( [ A - Z ] + ) ( [ A - Z ] [ a - z ] ) / g, '$1 $2' )
196+ . split ( / [ \s _ - ] + / )
197+ . map ( word => word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) )
198+ . join ( ' ' ) ;
199+ }
200+
176201 async connect ( transport : Transport ) {
177202 // The SDK will handle stdio communication
178203 await this . server . connect ( transport )
0 commit comments