Skip to content

Commit e6e6517

Browse files
committed
add sqlite server
1 parent 6e4d59f commit e6e6517

9 files changed

Lines changed: 500 additions & 7 deletions

File tree

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This repository contains a collection of reference MCP Streaming HTTP servers de
1515
1. Choose your preferred Pomerium installation method below.
1616
2. Configure the relevant MCP server(s):
1717
- [Notion](./notion/README.md): A tailored Notion MCP server that uses Notion OAuth for the current user and specifically implements [OpenAI Deep Researcher requirements](https://platform.openai.com/docs/mcp).
18+
- [SQLite](./sqlite/README.md): A simple readonly MCP server that can query SQLite databases.
1819

1920
## Docker Compose Example
2021

@@ -63,7 +64,9 @@ volumes:
6364

6465
# How does it work
6566

66-
[![MCP Webinar](https://img.youtube.com/vi/p0UJ_VlaWxY/0.jpg)](https://www.youtube.com/watch?v=p0UJ_VlaWxY)
67+
<a href="http://www.youtube.com/watch?feature=player_embedded&v=p0UJ_VlaWxY
68+
" target="_blank"><img src="http://img.youtube.com/vi/p0UJ_VlaWxY/0.jpg"
69+
alt="MCP in the Enterprise Environment" width="240" height="180" border="10" /></a>
6770

6871
## Token Vocabulary
6972

go.mod

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,20 @@ go 1.24.2
55
require (
66
github.com/jomei/notionapi v1.13.3
77
github.com/mark3labs/mcp-go v0.31.0
8+
modernc.org/sqlite v1.38.0
89
)
910

1011
require (
12+
github.com/dustin/go-humanize v1.0.1 // indirect
1113
github.com/google/uuid v1.6.0 // indirect
14+
github.com/mattn/go-isatty v0.0.20 // indirect
15+
github.com/ncruces/go-strftime v0.1.9 // indirect
16+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
1217
github.com/spf13/cast v1.7.1 // indirect
1318
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
19+
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
20+
golang.org/x/sys v0.33.0 // indirect
21+
modernc.org/libc v1.65.10 // indirect
22+
modernc.org/mathutil v1.7.1 // indirect
23+
modernc.org/memory v1.11.0 // indirect
1424
)

go.sum

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
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/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
4+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
35
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
46
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
5-
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
6-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
7+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
8+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
9+
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
10+
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
711
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
812
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
913
github.com/jomei/notionapi v1.13.3 h1:pzEN+pVe1T0FjH85sP9TCqqe58rFRL+Fj+F5yvyBNw4=
@@ -14,8 +18,14 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1418
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
1519
github.com/mark3labs/mcp-go v0.31.0 h1:4UxSV8aM770OPmTvaVe/b1rA2oZAjBMhGBfUgOGut+4=
1620
github.com/mark3labs/mcp-go v0.31.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
21+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
22+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
23+
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
24+
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
1725
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1826
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
27+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
28+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
1929
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
2030
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
2131
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
@@ -24,5 +34,40 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
2434
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
2535
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
2636
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
37+
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
38+
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
39+
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
40+
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
41+
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
42+
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
43+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
44+
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
45+
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
46+
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
47+
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
2748
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
2849
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
50+
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
51+
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
52+
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
53+
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
54+
modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
55+
modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
56+
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
57+
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
58+
modernc.org/libc v1.65.10 h1:ZwEk8+jhW7qBjHIT+wd0d9VjitRyQef9BnzlzGwMODc=
59+
modernc.org/libc v1.65.10/go.mod h1:StFvYpx7i/mXtBAfVOjaU0PWZOvIRoZSgXhrwXzr8Po=
60+
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
61+
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
62+
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
63+
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
64+
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
65+
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
66+
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
67+
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
68+
modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI=
69+
modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE=
70+
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
71+
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
72+
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
73+
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

notion/provider.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strings"
1010

1111
"github.com/jomei/notionapi"
12+
"github.com/mark3labs/mcp-go/server"
1213

1314
"github.com/pomerium/mcp-servers/ctxutil"
1415
"github.com/pomerium/mcp-servers/drutil"
@@ -21,6 +22,12 @@ func New(context.Context) drutil.Provider {
2122
}
2223
}
2324

25+
func NewServer(ctx context.Context, _ map[string]string) (*server.MCPServer, error) {
26+
provider := New(ctx)
27+
mcpServer := drutil.BuildMCPServer("Notion", provider)
28+
return mcpServer, nil
29+
}
30+
2431
//go:embed search.txt
2532
var searchDescription string
2633

server/builder.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,34 @@ package server
22

33
import (
44
"context"
5+
"log/slog"
56
"net/http"
67
"path"
8+
"strings"
79

810
"github.com/mark3labs/mcp-go/server"
911

1012
"github.com/pomerium/mcp-servers/ctxutil"
11-
"github.com/pomerium/mcp-servers/drutil"
1213
"github.com/pomerium/mcp-servers/notion"
14+
"github.com/pomerium/mcp-servers/sqlite"
1315
)
1416

1517
func BuildHandlers(ctx context.Context) http.Handler {
1618
mux := http.NewServeMux()
1719

18-
for name, builder := range map[string]drutil.Provider{
19-
"notion": notion.New(ctx),
20+
for name, builder := range map[string]func(
21+
ctx context.Context,
22+
env map[string]string,
23+
) (*server.MCPServer, error){
24+
"notion": notion.NewServer,
25+
"sqlite": sqlite.NewServer,
2026
} {
21-
mcpServer := drutil.BuildMCPServer(name, builder)
27+
mcpServer, err := builder(ctx, getEnvByPrefix(strings.ToUpper(name)+"_"))
28+
if err != nil {
29+
slog.Error("Not enabling", "name", name, "error", err)
30+
continue
31+
}
32+
slog.Info("Enabled", "name", name)
2233
httpHandler := server.NewStreamableHTTPServer(mcpServer,
2334
server.WithHTTPContextFunc(ctxutil.TokenFromRequest),
2435
)

server/env.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package server
2+
3+
import (
4+
"os"
5+
"strings"
6+
)
7+
8+
// getEnvByPrefix returns a map of environment variables that start with the given prefix
9+
// The prefix is removed from the keys in the returned map
10+
func getEnvByPrefix(prefix string) map[string]string {
11+
result := make(map[string]string)
12+
13+
for _, env := range os.Environ() {
14+
parts := strings.SplitN(env, "=", 2)
15+
if len(parts) == 2 && strings.HasPrefix(parts[0], prefix) {
16+
key := strings.TrimPrefix(parts[0], prefix)
17+
result[key] = parts[1]
18+
}
19+
}
20+
21+
return result
22+
}

server/env_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package server
2+
3+
import (
4+
"os"
5+
"strings"
6+
"testing"
7+
)
8+
9+
func TestGetEnvByPrefix(t *testing.T) {
10+
testEnvs := map[string]string{
11+
"TEST_VAR1": "value1",
12+
"TEST_VAR2": "value2",
13+
"OTHER_VAR": "othervalue",
14+
"TEST_NESTED_X": "nestedvalue",
15+
"NOTTEST_VAR": "nottest",
16+
}
17+
18+
// Set environment variables
19+
for k, v := range testEnvs {
20+
t.Setenv(k, v)
21+
}
22+
23+
tests := []struct {
24+
name string
25+
prefix string
26+
expected map[string]string
27+
}{
28+
{
29+
name: "TEST_ prefix",
30+
prefix: "TEST_",
31+
expected: map[string]string{
32+
"VAR1": "value1",
33+
"VAR2": "value2",
34+
"NESTED_X": "nestedvalue",
35+
},
36+
},
37+
{
38+
name: "OTHER_ prefix",
39+
prefix: "OTHER_",
40+
expected: map[string]string{
41+
"VAR": "othervalue",
42+
},
43+
},
44+
{
45+
name: "nonexistent prefix",
46+
prefix: "NONEXISTENT_",
47+
expected: map[string]string{},
48+
},
49+
{
50+
name: "empty prefix returns all vars",
51+
prefix: "",
52+
expected: func() map[string]string {
53+
result := make(map[string]string)
54+
for _, env := range os.Environ() {
55+
parts := strings.SplitN(env, "=", 2)
56+
if len(parts) == 2 {
57+
result[parts[0]] = parts[1]
58+
}
59+
}
60+
return result
61+
}(),
62+
},
63+
}
64+
65+
for _, tt := range tests {
66+
t.Run(tt.name, func(t *testing.T) {
67+
result := getEnvByPrefix(tt.prefix)
68+
69+
// For empty prefix test, just check that our test vars are present
70+
if tt.prefix == "" {
71+
for expectedKey, expectedValue := range testEnvs {
72+
if result[expectedKey] != expectedValue {
73+
t.Errorf("expected %s=%s, got %s", expectedKey, expectedValue, result[expectedKey])
74+
}
75+
}
76+
return
77+
}
78+
79+
// For other tests, check exact match
80+
if len(result) != len(tt.expected) {
81+
t.Errorf("expected %d items, got %d", len(tt.expected), len(result))
82+
}
83+
84+
for expectedKey, expectedValue := range tt.expected {
85+
if result[expectedKey] != expectedValue {
86+
t.Errorf("expected %s=%s, got %s", expectedKey, expectedValue, result[expectedKey])
87+
}
88+
}
89+
90+
// Verify prefix is actually removed
91+
for key := range result {
92+
if strings.HasPrefix(key, tt.prefix) && tt.prefix != "" {
93+
t.Errorf("prefix %s was not removed from key %s", tt.prefix, key)
94+
}
95+
}
96+
})
97+
}
98+
}

sqlite/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Overview
2+
3+
This is a simple SQLite MCP server that allows to query the SQLite database.
4+
5+
# Configuration
6+
7+
You need to set the following environment variables:
8+
9+
- `SQLITE_DB_FILE`: file path to sqlite database.

0 commit comments

Comments
 (0)