Skip to content
This repository was archived by the owner on Jun 29, 2025. It is now read-only.

Commit 5f8cd16

Browse files
committed
up
1 parent 7378233 commit 5f8cd16

File tree

4 files changed

+967
-588
lines changed

4 files changed

+967
-588
lines changed

cmd/openapi-mcp/flags.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type cliFlags struct {
3535
mounts mountFlags // slice of mountFlag
3636
functionListFile string // Path to file listing functions to include (for filter command)
3737
logFile string // Path to file for logging MCP requests and responses
38+
noLogTruncation bool // Disable truncation in human-readable MCP logs
3839
}
3940

4041
type mountFlag struct {
@@ -90,6 +91,7 @@ func parseFlags() *cliFlags {
9091
flag.Var(&flags.mounts, "mount", "Mount an OpenAPI spec at a base path: /base:path/to/spec.yaml (repeatable, can be used multiple times)")
9192
flag.StringVar(&flags.functionListFile, "function-list-file", "", "File with list of function (operationId) names to include (one per line, for filter command)")
9293
flag.StringVar(&flags.logFile, "log-file", "", "File path to log all MCP requests and responses for debugging")
94+
flag.BoolVar(&flags.noLogTruncation, "no-log-truncation", false, "Disable truncation of long values in human-readable MCP logs")
9395
flag.Parse()
9496
flags.args = flag.Args()
9597
if flags.extended {
@@ -197,6 +199,7 @@ Flags:
197199
--mount /base:path/to/spec.yaml Mount an OpenAPI spec at a base path (repeatable, can be used multiple times)
198200
--function-list-file File with list of function (operationId) names to include (one per line, for filter command)
199201
--log-file File path to log all MCP requests and responses for debugging
202+
--no-log-truncation Disable truncation of long values in human-readable MCP logs
200203
--help, -h Show help
201204
202205
By default, output is minimal and agent-friendly. Use --extended for banners, help, and human-readable output.

cmd/openapi-mcp/server.go

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func startServer(flags *cliFlags, ops []openapi2mcp.OpenAPIOperation, doc *opena
4848
os.Exit(1)
4949
}
5050
ops = openapi2mcp.ExtractOpenAPIOperations(d)
51-
srv, logFileHandle := createServerWithOptions("openapi-mcp", d.Info.Version, d, ops, flags.logFile)
51+
srv, logFileHandle := createServerWithOptions("openapi-mcp", d.Info.Version, d, ops, flags.logFile, flags.noLogTruncation)
5252
if logFileHandle != nil {
5353
defer logFileHandle.Close()
5454
}
@@ -82,7 +82,7 @@ func startServer(flags *cliFlags, ops []openapi2mcp.OpenAPIOperation, doc *opena
8282
os.Exit(1)
8383
}
8484
ops := openapi2mcp.ExtractOpenAPIOperations(d)
85-
srv, logFileHandle := createServerWithOptions("openapi-mcp", d.Info.Version, d, ops, flags.logFile)
85+
srv, logFileHandle := createServerWithOptions("openapi-mcp", d.Info.Version, d, ops, flags.logFile, flags.noLogTruncation)
8686
if logFileHandle != nil {
8787
defer logFileHandle.Close()
8888
}
@@ -113,7 +113,7 @@ func startServer(flags *cliFlags, ops []openapi2mcp.OpenAPIOperation, doc *opena
113113
os.Exit(1)
114114
}
115115
ops = openapi2mcp.ExtractOpenAPIOperations(d)
116-
srv, logFileHandle := createServerWithOptions("openapi-mcp", d.Info.Version, d, ops, flags.logFile)
116+
srv, logFileHandle := createServerWithOptions("openapi-mcp", d.Info.Version, d, ops, flags.logFile, flags.noLogTruncation)
117117
if logFileHandle != nil {
118118
defer logFileHandle.Close()
119119
}
@@ -131,7 +131,7 @@ func makeMCPHandler(srv *mcpserver.MCPServer, basePath string) http.Handler {
131131
}
132132

133133
// formatHumanReadableLog creates a human-readable log entry for MCP transactions
134-
func formatHumanReadableLog(timestamp, logType, method string, id any, data interface{}, err error) string {
134+
func formatHumanReadableLog(timestamp, logType, method string, id any, data interface{}, err error, noTruncation bool) string {
135135
var log strings.Builder
136136

137137
// Header with timestamp and type
@@ -158,7 +158,7 @@ func formatHumanReadableLog(timestamp, logType, method string, id any, data inte
158158
if len(args) > 0 {
159159
log.WriteString("📝 Arguments:\n")
160160
for key, value := range args {
161-
valueStr := formatValue(value)
161+
valueStr := formatValue(value, noTruncation)
162162
log.WriteString(fmt.Sprintf(" %s: %s\n", key, valueStr))
163163
}
164164
} else {
@@ -206,16 +206,16 @@ func formatHumanReadableLog(timestamp, logType, method string, id any, data inte
206206
case *mcp.ListToolsResult:
207207
tools := result.Tools
208208
log.WriteString(fmt.Sprintf("🔧 Tools Listed: %d tools\n", len(tools)))
209-
if len(tools) <= 10 {
210-
// Show all tools if 10 or fewer
209+
if noTruncation || len(tools) <= 10 {
210+
// Show all tools if no truncation or 10 or fewer
211211
for i, tool := range tools {
212212
desc := ""
213213
if len(tool.Description) > 0 {
214214
// Extract first line of description for brevity
215215
lines := strings.Split(tool.Description, "\n")
216216
if len(lines) > 0 {
217217
desc = lines[0]
218-
if len(desc) > 80 {
218+
if !noTruncation && len(desc) > 80 {
219219
desc = desc[:80] + "..."
220220
}
221221
}
@@ -230,7 +230,7 @@ func formatHumanReadableLog(timestamp, logType, method string, id any, data inte
230230
lines := strings.Split(tools[i].Description, "\n")
231231
if len(lines) > 0 {
232232
desc = lines[0]
233-
if len(desc) > 80 {
233+
if !noTruncation && len(desc) > 80 {
234234
desc = desc[:80] + "..."
235235
}
236236
}
@@ -246,7 +246,7 @@ func formatHumanReadableLog(timestamp, logType, method string, id any, data inte
246246
if textContent, ok := item.(mcp.TextContent); ok {
247247
log.WriteString(fmt.Sprintf(" [%d] Type: %s\n", i+1, textContent.Type))
248248
// Truncate very long responses
249-
if len(textContent.Text) > 500 {
249+
if !noTruncation && len(textContent.Text) > 500 {
250250
log.WriteString(fmt.Sprintf(" [%d] Text: %s... (%d chars total)\n",
251251
i+1, textContent.Text[:500], len(textContent.Text)))
252252
} else {
@@ -267,7 +267,7 @@ func formatHumanReadableLog(timestamp, logType, method string, id any, data inte
267267
}
268268
if text, ok := contentItem["text"].(string); ok {
269269
// Truncate very long responses
270-
if len(text) > 500 {
270+
if !noTruncation && len(text) > 500 {
271271
log.WriteString(fmt.Sprintf(" [%d] Text: %s... (%d chars total)\n",
272272
i+1, text[:500], len(text)))
273273
} else {
@@ -279,8 +279,8 @@ func formatHumanReadableLog(timestamp, logType, method string, id any, data inte
279279
}
280280
} else if tools, ok := result["tools"].([]interface{}); ok {
281281
log.WriteString(fmt.Sprintf("🔧 Tools Listed: %d tools\n", len(tools)))
282-
if len(tools) <= 10 {
283-
// Show all tools if 10 or fewer
282+
if noTruncation || len(tools) <= 10 {
283+
// Show all tools if no truncation or 10 or fewer
284284
for i, tool := range tools {
285285
if toolItem, ok := tool.(map[string]interface{}); ok {
286286
if name, ok := toolItem["name"].(string); ok {
@@ -345,10 +345,10 @@ func formatHumanReadableLog(timestamp, logType, method string, id any, data inte
345345
}
346346

347347
// formatValue formats a value for human-readable display
348-
func formatValue(value interface{}) string {
348+
func formatValue(value interface{}, noTruncation bool) string {
349349
switch v := value.(type) {
350350
case string:
351-
if len(v) > 100 {
351+
if !noTruncation && len(v) > 100 {
352352
return fmt.Sprintf("\"%s...\" (%d chars)", v[:100], len(v))
353353
}
354354
return fmt.Sprintf("\"%s\"", v)
@@ -360,7 +360,7 @@ func formatValue(value interface{}) string {
360360
for k := range v {
361361
keys = append(keys, k)
362362
}
363-
if len(keys) > 3 {
363+
if !noTruncation && len(keys) > 3 {
364364
return fmt.Sprintf("{%s, ...} (%d keys)", strings.Join(keys[:3], ", "), len(keys))
365365
}
366366
return fmt.Sprintf("{%s}", strings.Join(keys, ", "))
@@ -372,7 +372,7 @@ func formatValue(value interface{}) string {
372372
}
373373

374374
// createLoggingHooks creates MCP hooks for logging requests and responses to a file
375-
func createLoggingHooks(logFilePath string) (*mcpserver.Hooks, *os.File, error) {
375+
func createLoggingHooks(logFilePath string, noLogTruncation bool) (*mcpserver.Hooks, *os.File, error) {
376376
logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
377377
if err != nil {
378378
return nil, nil, fmt.Errorf("failed to open log file: %w", err)
@@ -385,34 +385,34 @@ func createLoggingHooks(logFilePath string) (*mcpserver.Hooks, *os.File, error)
385385
// Log requests with human-readable format
386386
hooks.AddBeforeAny(func(ctx context.Context, id any, method mcp.MCPMethod, message any) {
387387
timestamp := time.Now().Format("2006-01-02 15:04:05 MST")
388-
humanLog := formatHumanReadableLog(timestamp, "request", string(method), id, message, nil)
388+
humanLog := formatHumanReadableLog(timestamp, "request", string(method), id, message, nil, noLogTruncation)
389389
logger.Print(humanLog)
390390
})
391391

392392
// Log successful responses with human-readable format
393393
hooks.AddOnSuccess(func(ctx context.Context, id any, method mcp.MCPMethod, message any, result any) {
394394
timestamp := time.Now().Format("2006-01-02 15:04:05 MST")
395-
humanLog := formatHumanReadableLog(timestamp, "response", string(method), id, result, nil)
395+
humanLog := formatHumanReadableLog(timestamp, "response", string(method), id, result, nil, noLogTruncation)
396396
logger.Print(humanLog)
397397
})
398398

399399
// Log errors with human-readable format
400400
hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
401401
timestamp := time.Now().Format("2006-01-02 15:04:05 MST")
402-
humanLog := formatHumanReadableLog(timestamp, "error", string(method), id, message, err)
402+
humanLog := formatHumanReadableLog(timestamp, "error", string(method), id, message, err, noLogTruncation)
403403
logger.Print(humanLog)
404404
})
405405

406406
return hooks, logFile, nil
407407
}
408408

409409
// createServerWithOptions creates a new MCP server with the given operations and optional logging
410-
func createServerWithOptions(name, version string, doc *openapi3.T, ops []openapi2mcp.OpenAPIOperation, logFile string) (*mcpserver.MCPServer, *os.File) {
410+
func createServerWithOptions(name, version string, doc *openapi3.T, ops []openapi2mcp.OpenAPIOperation, logFile string, noLogTruncation bool) (*mcpserver.MCPServer, *os.File) {
411411
var opts []mcpserver.ServerOption
412412
var logFileHandle *os.File
413413

414414
if logFile != "" {
415-
hooks, fileHandle, err := createLoggingHooks(logFile)
415+
hooks, fileHandle, err := createLoggingHooks(logFile, noLogTruncation)
416416
if err != nil {
417417
fmt.Fprintf(os.Stderr, "Failed to create logging hooks: %v\n", err)
418418
os.Exit(1)

0 commit comments

Comments
 (0)