@@ -53,28 +53,57 @@ declare const spec: {
5353 * e.g. GET /accounts/{account_id}/workers/scripts → get_accounts_workers_scripts
5454 */
5555export function pathToToolName ( method : string , path : string ) : string {
56+ return `${ method . toLowerCase ( ) } _${ pathToToolNameSuffix ( path ) } `
57+ }
58+
59+ function pathToToolNameSuffix ( path : string ) : string {
5660 let cleaned = path
5761
5862 // Check if path ends with a {param} — keep it for disambiguation
5963 const trailingParam = cleaned . match ( / \/ \{ ( [ ^ } ] + ) \} $ / )
6064 const suffix = trailingParam ? `_by_${ trailingParam [ 1 ] } ` : ''
6165
6266 const name =
63- method . toLowerCase ( ) +
64- '_' +
6567 cleaned
6668 . replace ( / ^ \/ / , '' )
6769 . replace ( / \/ \{ [ ^ } ] + \} / g, '' ) // strip all {param} segments
6870 . replace ( / \/ / g, '_' )
6971 . replace ( / [ ^ a - z 0 - 9 _ ] / gi, '' )
7072 . replace ( / _ + / g, '_' )
71- . replace ( / _ $ / , '' ) +
72- suffix
73+ . replace ( / _ $ / , '' ) + suffix
7374
7475 // MCP spec: tool names SHOULD be between 1 and 128 characters
7576 return name . length > 128 ? name . slice ( 0 , 128 ) . replace ( / _ $ / , '' ) : name
7677}
7778
79+ /**
80+ * Build a human-readable title for a non-Code-Mode tool from its
81+ * machine-friendly name. The title mirrors the tool name structure but with
82+ * each segment title-cased so clients can display consistent, readable labels.
83+ *
84+ * e.g. get_accounts_workers_scripts → Get Accounts Workers Scripts
85+ */
86+ export function toolNameToTitle ( name : string ) : string {
87+ const withPrepositions = name
88+ . replace ( / _ b y _ / g, ' by ' )
89+ . replace ( / _ f o r _ / g, ' for ' )
90+ . replace ( / _ i n _ / g, ' in ' )
91+ . replace ( / _ o f _ / g, ' of ' )
92+ . replace ( / _ o n _ / g, ' on ' )
93+ . replace ( / _ t o _ / g, ' to ' )
94+ . replace ( / _ w i t h _ / g, ' with ' )
95+ return withPrepositions . replace ( / _ / g, ' ' ) . replace ( / \b \w / g, ( letter , offset ) =>
96+ // Keep prepositions lower-case when preceded by a space and followed by a space/end.
97+ offset > 0 &&
98+ / \s / . test ( withPrepositions [ offset - 1 ] ?? '' ) &&
99+ [ 'by ' , 'for ' , 'in ' , 'of ' , 'on ' , 'to ' , 'with ' ] . some ( ( prep ) =>
100+ withPrepositions . slice ( offset ) . toLowerCase ( ) . startsWith ( prep )
101+ )
102+ ? letter . toLowerCase ( )
103+ : letter . toUpperCase ( )
104+ )
105+ }
106+
78107const HTTP_METHODS = [ 'get' , 'post' , 'put' , 'patch' , 'delete' ] as const
79108
80109export type HttpMethod = ( typeof HTTP_METHODS ) [ number ]
@@ -92,6 +121,7 @@ export type JsonObjectSchema = {
92121 */
93122export interface NonCodemodeTool {
94123 name : string
124+ title ?: string
95125 description : string
96126 inputSchema : JsonObjectSchema
97127 method : HttpMethod
@@ -159,6 +189,7 @@ export function buildNonCodemodeTools(
159189 return listNonCodemodeOperations ( paths ) . map (
160190 ( { toolName, description, method, path, operation } ) => ( {
161191 name : toolName ,
192+ title : toolNameToTitle ( toolName ) ,
162193 description,
163194 inputSchema : buildJsonInputSchema ( operation , path ) ,
164195 method,
0 commit comments