Skip to content

Commit 33390d5

Browse files
committed
Updates
1 parent 8ddab61 commit 33390d5

File tree

6 files changed

+203
-49
lines changed

6 files changed

+203
-49
lines changed

.github/workflows/release.yml

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,57 @@
1-
name: "Create Release on Tag Push"
1+
name: Release
2+
23
on:
34
push:
45
tags:
5-
- '*'
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
packages: write
11+
612
jobs:
7-
release:
13+
goreleaser:
814
runs-on: ubuntu-latest
9-
1015
steps:
11-
- name: Checkout Code
12-
uses: actions/checkout@v3
13-
14-
- name: Create GitHub Release
15-
uses: actions/create-release@v1
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
21+
- name: Set up Go
22+
uses: actions/setup-go@v5
23+
with:
24+
go-version: '>=1.21.0'
25+
check-latest: true
26+
27+
- name: Run GoReleaser
28+
uses: goreleaser/goreleaser-action@v5
29+
with:
30+
distribution: goreleaser
31+
version: '2'
32+
args: release --clean
1633
env:
1734
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+
36+
- name: Extract version
37+
id: get-version
38+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
39+
40+
- name: Login to GitHub Container Registry
41+
uses: docker/login-action@v3
42+
with:
43+
registry: ghcr.io
44+
username: ${{ github.repository_owner }}
45+
password: ${{ secrets.GITHUB_TOKEN }}
46+
47+
- name: Set up Docker Buildx
48+
uses: docker/setup-buildx-action@v3
49+
50+
- name: Build and push Docker image
51+
uses: docker/build-push-action@v5
1852
with:
19-
tag_name: ${{ github.ref }}
20-
release_name: Release ${{ github.ref }}
21-
draft: false
22-
prerelease: false
53+
context: .
54+
push: true
55+
tags: |
56+
ghcr.io/${{ github.repository }}:latest
57+
ghcr.io/${{ github.repository }}:${{ steps.get-version.outputs.VERSION }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
.aider*
2+
.opencode*
3+
OpenCode.md

.goreleaser.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
version: 2
2+
3+
before:
4+
hooks:
5+
- go mod tidy
6+
7+
builds:
8+
- id: mcp-filesystem-server
9+
env:
10+
- CGO_ENABLED=0
11+
goos:
12+
- linux
13+
- windows
14+
- darwin
15+
goarch:
16+
- amd64
17+
- arm64
18+
ldflags:
19+
- -s -w
20+
binary: mcp-filesystem-server
21+
main: .
22+
23+
archives:
24+
- id: default
25+
format_overrides:
26+
- goos: windows
27+
formats:
28+
- zip
29+
name_template: >-
30+
{{ .ProjectName }}_
31+
{{- .Os }}_
32+
{{- .Arch }}
33+
files:
34+
- README.md
35+
- LICENSE*
36+
37+
checksum:
38+
name_template: 'checksums.txt'
39+
algorithm: sha256
40+
41+
# Using new snapshot configuration
42+
snapshot:
43+
name_template: "{{ .Version }}-SNAPSHOT-{{ .ShortCommit }}"
44+
45+
changelog:
46+
sort: asc
47+
filters:
48+
exclude:
49+
- '^docs:'
50+
- '^test:'
51+
- Merge pull request
52+
- Merge branch
53+
54+
release:
55+
github:
56+
owner: mark3labs
57+
name: mcp-filesystem-server
58+
draft: false
59+
prerelease: auto
60+
name_template: "{{ .Tag }}"
61+
mode: replace

go.mod

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ module github.com/mark3labs/mcp-filesystem-server
22

33
go 1.23.2
44

5-
require github.com/mark3labs/mcp-go v0.11.2
5+
require (
6+
github.com/gabriel-vasile/mimetype v1.4.3
7+
github.com/mark3labs/mcp-go v0.26.0
8+
)
69

7-
require github.com/google/uuid v1.6.0 // indirect
10+
require (
11+
github.com/google/uuid v1.6.0 // indirect
12+
github.com/spf13/cast v1.7.1 // indirect
13+
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
14+
golang.org/x/net v0.21.0 // indirect
15+
)

go.sum

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
4+
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
5+
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
6+
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
7+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
8+
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
39
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
410
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
5-
github.com/mark3labs/mcp-go v0.11.2 h1:mCxWFUTrcXOtJIn9t7F8bxAL8rpE/ZZTTnx3PU/VNdA=
6-
github.com/mark3labs/mcp-go v0.11.2/go.mod h1:cjMlBU0cv/cj9kjlgmRhoJ5JREdS7YX83xeIG9Ko/jE=
11+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
12+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
13+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
14+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
15+
github.com/mark3labs/mcp-go v0.26.0 h1:xz/Kv1cHLYovF8txv6btBM39/88q3YOjnxqhi51jB0w=
16+
github.com/mark3labs/mcp-go v0.26.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
717
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
818
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
19+
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
20+
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
21+
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
22+
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
923
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
1024
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
25+
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
26+
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
27+
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
28+
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
1129
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1230
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

main.go

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77
"fmt"
88
"log"
99
"mime"
10-
"net/http"
1110
"os"
1211
"path/filepath"
1312
"strings"
1413
"time"
1514

15+
"github.com/gabriel-vasile/mimetype"
1616
"github.com/mark3labs/mcp-go/mcp"
1717
"github.com/mark3labs/mcp-go/server"
1818
)
@@ -392,47 +392,77 @@ func (s *FilesystemServer) searchFiles(
392392

393393
// detectMimeType tries to determine the MIME type of a file
394394
func detectMimeType(path string) string {
395-
// First try by extension
396-
ext := filepath.Ext(path)
397-
if ext != "" {
398-
mimeType := mime.TypeByExtension(ext)
399-
if mimeType != "" {
400-
return mimeType
401-
}
402-
}
403-
404-
// If that fails, try to read a bit of the file
405-
file, err := os.Open(path)
406-
if err != nil {
407-
return "application/octet-stream" // Default
408-
}
409-
defer file.Close()
410-
411-
// Read first 512 bytes to detect content type
412-
buffer := make([]byte, 512)
413-
n, err := file.Read(buffer)
395+
// Use mimetype library for more accurate detection
396+
mtype, err := mimetype.DetectFile(path)
414397
if err != nil {
398+
// Fallback to extension-based detection if file can't be read
399+
ext := filepath.Ext(path)
400+
if ext != "" {
401+
mimeType := mime.TypeByExtension(ext)
402+
if mimeType != "" {
403+
return mimeType
404+
}
405+
}
415406
return "application/octet-stream" // Default
416407
}
417-
418-
// Use http.DetectContentType
419-
return http.DetectContentType(buffer[:n])
408+
409+
return mtype.String()
420410
}
421411

422412
// isTextFile determines if a file is likely a text file based on MIME type
423413
func isTextFile(mimeType string) bool {
424-
return strings.HasPrefix(mimeType, "text/") ||
425-
mimeType == "application/json" ||
426-
mimeType == "application/xml" ||
427-
mimeType == "application/javascript" ||
428-
mimeType == "application/x-javascript" ||
429-
strings.Contains(mimeType, "+xml") ||
430-
strings.Contains(mimeType, "+json")
414+
// Check for common text MIME types
415+
if strings.HasPrefix(mimeType, "text/") {
416+
return true
417+
}
418+
419+
// Common application types that are text-based
420+
textApplicationTypes := []string{
421+
"application/json",
422+
"application/xml",
423+
"application/javascript",
424+
"application/x-javascript",
425+
"application/typescript",
426+
"application/x-typescript",
427+
"application/x-yaml",
428+
"application/yaml",
429+
"application/toml",
430+
"application/x-sh",
431+
"application/x-shellscript",
432+
}
433+
434+
for _, textType := range textApplicationTypes {
435+
if mimeType == textType {
436+
return true
437+
}
438+
}
439+
440+
// Check for +format types
441+
if strings.Contains(mimeType, "+xml") ||
442+
strings.Contains(mimeType, "+json") ||
443+
strings.Contains(mimeType, "+yaml") {
444+
return true
445+
}
446+
447+
// Common code file types that might be misidentified
448+
if strings.HasPrefix(mimeType, "text/x-") {
449+
return true
450+
}
451+
452+
if strings.HasPrefix(mimeType, "application/x-") &&
453+
(strings.Contains(mimeType, "script") ||
454+
strings.Contains(mimeType, "source") ||
455+
strings.Contains(mimeType, "code")) {
456+
return true
457+
}
458+
459+
return false
431460
}
432461

433462
// isImageFile determines if a file is an image based on MIME type
434463
func isImageFile(mimeType string) bool {
435-
return strings.HasPrefix(mimeType, "image/")
464+
return strings.HasPrefix(mimeType, "image/") ||
465+
(mimeType == "application/xml" && strings.HasSuffix(strings.ToLower(mimeType), ".svg"))
436466
}
437467

438468
// pathToResourceURI converts a file path to a resource URI
@@ -674,7 +704,7 @@ func (s *FilesystemServer) handleReadFile(
674704
}, nil
675705
}
676706

677-
// Handle based on content type
707+
// Check if it's a text file
678708
if isTextFile(mimeType) {
679709
// It's a text file, return as text
680710
return &mcp.CallToolResult{

0 commit comments

Comments
 (0)