Skip to main content
Glama

Filesystem MCP Server

by mark3labs
package handler import ( "context" "encoding/base64" "fmt" "os" "github.com/mark3labs/mcp-go/mcp" ) func (fs *FilesystemHandler) HandleReadFile( ctx context.Context, request mcp.CallToolRequest, ) (*mcp.CallToolResult, error) { path, err := request.RequireString("path") if err != nil { return nil, err } // Handle empty or relative paths like "." or "./" by converting to absolute path if path == "." || path == "./" { // Get current working directory cwd, err := os.Getwd() if err != nil { return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Error resolving current directory: %v", err), }, }, IsError: true, }, nil } path = cwd } validPath, err := fs.validatePath(path) if err != nil { return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Error: %v", err), }, }, IsError: true, }, nil } // Check if it's a directory info, err := os.Stat(validPath) if err != nil { return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Error: %v", err), }, }, IsError: true, }, nil } if info.IsDir() { // For directories, return a resource reference instead resourceURI := pathToResourceURI(validPath) return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("This is a directory. Use the resource URI to browse its contents: %s", resourceURI), }, mcp.EmbeddedResource{ Type: "resource", Resource: mcp.TextResourceContents{ URI: resourceURI, MIMEType: "text/plain", Text: fmt.Sprintf("Directory: %s", validPath), }, }, }, }, nil } // Determine MIME type mimeType := detectMimeType(validPath) // Check file size if info.Size() > MAX_INLINE_SIZE { // File is too large to inline, return a resource reference resourceURI := pathToResourceURI(validPath) return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("File is too large to display inline (%d bytes). Access it via resource URI: %s", info.Size(), resourceURI), }, mcp.EmbeddedResource{ Type: "resource", Resource: mcp.TextResourceContents{ URI: resourceURI, MIMEType: "text/plain", Text: fmt.Sprintf("Large file: %s (%s, %d bytes)", validPath, mimeType, info.Size()), }, }, }, }, nil } // Read file content content, err := os.ReadFile(validPath) if err != nil { return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Error reading file: %v", err), }, }, IsError: true, }, nil } // Check if it's a text file if isTextFile(mimeType) { // It's a text file, return as text return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: string(content), }, }, }, nil } else if isImageFile(mimeType) { // It's an image file, return as image content if info.Size() <= MAX_BASE64_SIZE { return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Image file: %s (%s, %d bytes)", validPath, mimeType, info.Size()), }, mcp.ImageContent{ Type: "image", Data: base64.StdEncoding.EncodeToString(content), MIMEType: mimeType, }, }, }, nil } else { // Too large for base64, return a reference resourceURI := pathToResourceURI(validPath) return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Image file is too large to display inline (%d bytes). Access it via resource URI: %s", info.Size(), resourceURI), }, mcp.EmbeddedResource{ Type: "resource", Resource: mcp.TextResourceContents{ URI: resourceURI, MIMEType: "text/plain", Text: fmt.Sprintf("Large image: %s (%s, %d bytes)", validPath, mimeType, info.Size()), }, }, }, }, nil } } else { // It's another type of binary file resourceURI := pathToResourceURI(validPath) if info.Size() <= MAX_BASE64_SIZE { // Small enough for base64 encoding return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Binary file: %s (%s, %d bytes)", validPath, mimeType, info.Size()), }, mcp.EmbeddedResource{ Type: "resource", Resource: mcp.BlobResourceContents{ URI: resourceURI, MIMEType: mimeType, Blob: base64.StdEncoding.EncodeToString(content), }, }, }, }, nil } else { // Too large for base64, return a reference return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Binary file: %s (%s, %d bytes). Access it via resource URI: %s", validPath, mimeType, info.Size(), resourceURI), }, mcp.EmbeddedResource{ Type: "resource", Resource: mcp.TextResourceContents{ URI: resourceURI, MIMEType: "text/plain", Text: fmt.Sprintf("Binary file: %s (%s, %d bytes)", validPath, mimeType, info.Size()), }, }, }, }, nil } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mark3labs/mcp-filesystem-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server