Skip to content

Commit 9de2732

Browse files
authored
feat: v0.2.0 — multi-installation support and citation tools (#86)
* feat: support multiple installations via --config-dir flag (Closes #85) Add --config-dir flag and GSUITE_MCP_CONFIG_DIR env var to override the default config directory (~/.config/gsuite-mcp/). This enables running multiple gsuite-mcp instances with different GCP projects — e.g., one for a work Workspace account and another for a personal account. Each installation gets its own client_secret.json, config.json, and credentials/ directory. The .installations/ convention keeps repo-local configs gitignored. * docs: add changelog and update default OAuth port references to 38917 Add [Unreleased] section to CHANGELOG.md covering all changes since v0.1.0. Update all documentation and test references from port 8100 to 38917 to match the new DefaultOAuthPort constant. * chore: bump version to 0.2.0 New features since 0.1.0: multi-installation support, citation tools, Forms, Slides, Gmail send-as, Drive filtering, Docs/Sheets/Calendar enhancements, and OAuth port change. * feat(citation): add large document citation tools with FTS5 search Add 11 citation tools for indexing, searching, and citing large documents: - citation_create_index: Create Google Sheets index in a Drive folder - citation_add_documents: Chunk docs/slides/pptx, write to Sheets + SQLite - citation_lookup: FTS5 full-text search across indexed chunks - citation_get_overview: Index stats with doc/chunk counts and concepts - citation_get_chunks: Retrieve full chunk content by ID - citation_verify_claim: Find chunks supporting a claim - citation_format_citation: Human-readable citation with file/slide/snippet - citation_save_concepts: Persist LLM-extracted concept→chunk mappings - citation_save_summary: Persist hierarchical summaries - citation_list_indexes: List configured indexes - citation_refresh: Detect updated/removed/renamed files and re-index Architecture: dual-layer storage (Google Sheets as source of truth, SQLite FTS5 as disposable local cache). Cache auto-rebuilds from Sheets when missing. Feature-flagged via large_doc_indexing config. Supports Google Slides (native API), uploaded .pptx (zip/XML text extraction), Google Docs (text export), and shared drives (SupportsAllDrives). Large content responses get a citation hint when the feature is enabled.
1 parent d65c82d commit 9de2732

29 files changed

+3032
-20
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ rod-mcp.yaml
3434
!schemas/*.json
3535
credentials/
3636
.workflow-state.json
37+
38+
# Per-installation config directories (see #85)
39+
.installations/

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.2.0] - 2026-03-20
9+
10+
### Added
11+
12+
- **Multi-installation support**: `--config-dir` flag and `GSUITE_MCP_CONFIG_DIR` env var to run multiple instances with different GCP projects (#85)
13+
- **Citation tools** (11 tools): Large document indexing with chunking, FTS5 search, concept extraction, and citation formatting (feature-flagged via `large_doc_indexing`)
14+
- **Google Forms** (5 tools): Get form structure, create forms, batch update, list/get responses (#78)
15+
- **Google Slides** (5 tools): Read presentations, get slides, thumbnails, create, batch update (#77)
16+
- **Gmail send-as aliases and delegation** (9 tools): Manage send-as identities and delegate access (#79)
17+
- **Drive access filtering**: Configurable allowlist/blocklist for shared drives (#76)
18+
- **Docs enhancements**: Markdown export, find-replace, PDF export, doc import (#74)
19+
- **Docs styling and Sheets formatting**: Paragraph styles, charts, pivot tables (#73)
20+
- **Calendar enhancements**: Focus Time, OOO events, conference data, free/busy (#72)
21+
- **Drive enhancements**: Shareable links, file type filter, comments, revisions (#71)
22+
- Protocol-level MCP tests for regression prevention (#83)
23+
24+
### Changed
25+
26+
- Default OAuth port changed from `8100` to `38917` to avoid conflicts with common dev servers
27+
828
## [0.1.0] - 2026-02-09
929

1030
### Added

INSTALLATION.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ Re-run the auth command:
187187
gsuite-mcp auth
188188
```
189189

190-
Or, if gsuite-mcp is running as an MCP server, open `http://localhost:8100/auth` in your browser to re-authenticate without restarting the server. Error messages from tools will include this URL when the auth server is running.
190+
Or, if gsuite-mcp is running as an MCP server, open `http://localhost:38917/auth` in your browser to re-authenticate without restarting the server. Error messages from tools will include this URL when the auth server is running.
191191

192192
### API Not Enabled
193193

@@ -270,7 +270,7 @@ Optional configuration file created by `gsuite-mcp init`. Settings:
270270

271271
| Key | Default | Description |
272272
|-----|---------|-------------|
273-
| `oauth_port` | `8100` | Port for the OAuth callback server during `gsuite-mcp auth` |
273+
| `oauth_port` | `38917` | Port for the OAuth callback server during `gsuite-mcp auth` |
274274

275275
Override `oauth_port` via the `GSUITE_MCP_OAUTH_PORT` environment variable.
276276

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ See [INSTALLATION.md](INSTALLATION.md) for full setup instructions.
340340

341341
### OAuth Callback Port
342342

343-
The default OAuth callback port is **8100**. Override it in `config.json`:
343+
The default OAuth callback port is **38917**. Override it in `config.json`:
344344

345345
```json
346346
{ "oauth_port": 9000 }
@@ -354,7 +354,7 @@ Restrict which shared drives are accessible via MCP tools. Add `drive_access` to
354354

355355
```json
356356
{
357-
"oauth_port": 8100,
357+
"oauth_port": 38917,
358358
"drive_access": {
359359
"allowed": ["Marketing", "Engineering"]
360360
}
@@ -371,8 +371,8 @@ My Drive is always accessible. Setting both `allowed` and `blocked` is an error.
371371

372372
When running as an MCP server, gsuite-mcp starts a persistent HTTP server on the OAuth port so agents and users can trigger re-authentication from a browser:
373373

374-
- **`http://localhost:8100/auth`** — starts OAuth flow (opens Google consent screen)
375-
- **`http://localhost:8100/auth?account=user@gmail.com`** — pre-selects the Google account
374+
- **`http://localhost:38917/auth`** — starts OAuth flow (opens Google consent screen)
375+
- **`http://localhost:38917/auth?account=user@gmail.com`** — pre-selects the Google account
376376

377377
When a tool encounters missing credentials, the error message includes a clickable auth URL. If the port is unavailable, the MCP server continues without the auth endpoint.
378378

cmd/gsuite-mcp/main.go

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import (
44
"context"
55
"fmt"
66
"os"
7+
"path/filepath"
78
"time"
89

910
"github.com/aliwatters/gsuite-mcp/internal/auth"
1011
"github.com/aliwatters/gsuite-mcp/internal/calendar"
12+
"github.com/aliwatters/gsuite-mcp/internal/citation"
1113
"github.com/aliwatters/gsuite-mcp/internal/common"
1214
"github.com/aliwatters/gsuite-mcp/internal/config"
1315
"github.com/aliwatters/gsuite-mcp/internal/contacts"
@@ -23,10 +25,14 @@ import (
2325

2426
const (
2527
serverName = "gsuite-mcp"
26-
serverVersion = "0.1.0"
28+
serverVersion = "0.2.0"
2729
)
2830

2931
func main() {
32+
// Parse --config-dir flag or GSUITE_MCP_CONFIG_DIR env var before subcommand dispatch.
33+
// This must happen first so all config.* path functions resolve correctly.
34+
parseConfigDir()
35+
3036
// Check for subcommands first
3137
if len(os.Args) > 1 {
3238
switch os.Args[1] {
@@ -80,6 +86,9 @@ func main() {
8086
forms.RegisterTools(s)
8187
contacts.RegisterTools(s)
8288

89+
// Conditionally register citation tools (feature-flagged)
90+
registerCitationIfEnabled(s)
91+
8392
// Start server
8493
if err := server.ServeStdio(s); err != nil {
8594
fmt.Fprintf(os.Stderr, "Server error: %v\n", err)
@@ -138,17 +147,23 @@ Usage:
138147
No configuration required - just authenticate any Google account on demand.
139148
When tools request an account without credentials, auth flow is triggered automatically.
140149
150+
Flags:
151+
--config-dir DIR Use DIR for config, credentials, and client_secret.json
152+
(default: %s)
153+
141154
Configuration:
142155
Config dir: %s
143156
Config file: %s
144157
Credentials: %s
145158
Client secret: %s
146159
147160
Environment variables:
161+
GSUITE_MCP_CONFIG_DIR Override config directory (same as --config-dir)
148162
GSUITE_MCP_OAUTH_PORT Override OAuth callback port (default: %d)
149163
150164
For more information, see README.md
151165
`, serverName, serverName, serverName, serverName, serverName, serverName,
166+
config.DefaultConfigDir(),
152167
config.DefaultConfigDir(), config.ConfigPath(), config.CredentialsDir(), config.ClientSecretPath(),
153168
config.DefaultOAuthPort)
154169
}
@@ -218,6 +233,65 @@ func runAccounts() {
218233
fmt.Printf("\nRun '%s auth' to add another account.\n", serverName)
219234
}
220235

236+
// registerCitationIfEnabled registers citation tools if the large_doc_indexing feature is enabled.
237+
func registerCitationIfEnabled(s *server.MCPServer) {
238+
cfg, err := config.LoadConfig()
239+
if err != nil || cfg.Features == nil || !cfg.Features.LargeDocIndexing {
240+
return
241+
}
242+
243+
var citCfg *citation.CitationConfig
244+
if cfg.Citation != nil {
245+
citCfg = &citation.CitationConfig{
246+
Indexes: make(map[string]citation.IndexEntry),
247+
}
248+
for k, v := range cfg.Citation.Indexes {
249+
citCfg.Indexes[k] = citation.IndexEntry{SheetID: v.SheetID}
250+
}
251+
}
252+
253+
citation.InitDefaultDeps(citCfg)
254+
citation.RegisterTools(s)
255+
256+
// Enable citation hints on large content responses
257+
if d := common.GetDeps(); d != nil {
258+
d.CitationEnabled = true
259+
}
260+
261+
fmt.Fprintln(os.Stderr, "citation tools enabled (large_doc_indexing)")
262+
}
263+
264+
// parseConfigDir checks for --config-dir flag or GSUITE_MCP_CONFIG_DIR env var
265+
// and sets the config directory override. The flag is consumed from os.Args so
266+
// subcommand parsing is unaffected.
267+
func parseConfigDir() {
268+
// Check for --config-dir flag (must appear before subcommand)
269+
for i := 1; i < len(os.Args); i++ {
270+
if os.Args[i] == "--config-dir" && i+1 < len(os.Args) {
271+
dir := os.Args[i+1]
272+
absDir, err := filepath.Abs(dir)
273+
if err != nil {
274+
fmt.Fprintf(os.Stderr, "Error resolving --config-dir %q: %v\n", dir, err)
275+
os.Exit(1)
276+
}
277+
config.SetConfigDir(absDir)
278+
// Remove the flag and its value from os.Args
279+
os.Args = append(os.Args[:i], os.Args[i+2:]...)
280+
return
281+
}
282+
}
283+
284+
// Fall back to environment variable
285+
if dir := os.Getenv("GSUITE_MCP_CONFIG_DIR"); dir != "" {
286+
absDir, err := filepath.Abs(dir)
287+
if err != nil {
288+
fmt.Fprintf(os.Stderr, "Error resolving GSUITE_MCP_CONFIG_DIR %q: %v\n", dir, err)
289+
os.Exit(1)
290+
}
291+
config.SetConfigDir(absDir)
292+
}
293+
}
294+
221295
// startAuthServer starts a persistent HTTP auth server for browser-based re-authentication.
222296
// Returns nil if the port cannot be bound (non-fatal — MCP server continues without it).
223297
func startAuthServer() *auth.AuthServer {

docs/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ if err != nil {
165165

166166
#### HTTP Auth Endpoint
167167

168-
When running as an MCP server, gsuite-mcp starts a persistent HTTP auth server on the OAuth port. If a tool encounters missing credentials, the error message includes a clickable URL (e.g., `http://localhost:8100/auth?account=user@gmail.com`). Agents should surface this URL to the user rather than suggesting CLI commands.
168+
When running as an MCP server, gsuite-mcp starts a persistent HTTP auth server on the OAuth port. If a tool encounters missing credentials, the error message includes a clickable URL (e.g., `http://localhost:38917/auth?account=user@gmail.com`). Agents should surface this URL to the user rather than suggesting CLI commands.
169169

170170
### 4. Error Handling
171171

go.mod

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/aliwatters/gsuite-mcp
22

3-
go 1.24.0
3+
go 1.25.0
44

55
require (
66
github.com/mark3labs/mcp-go v0.23.1
@@ -13,13 +13,17 @@ require (
1313
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
1414
cloud.google.com/go/compute/metadata v0.9.0 // indirect
1515
github.com/cespare/xxhash/v2 v2.3.0 // indirect
16+
github.com/dustin/go-humanize v1.0.1 // indirect
1617
github.com/felixge/httpsnoop v1.0.4 // indirect
1718
github.com/go-logr/logr v1.4.3 // indirect
1819
github.com/go-logr/stdr v1.2.2 // indirect
1920
github.com/google/s2a-go v0.1.9 // indirect
2021
github.com/google/uuid v1.6.0 // indirect
2122
github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect
2223
github.com/googleapis/gax-go/v2 v2.16.0 // indirect
24+
github.com/mattn/go-isatty v0.0.20 // indirect
25+
github.com/ncruces/go-strftime v1.0.0 // indirect
26+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
2327
github.com/spf13/cast v1.7.1 // indirect
2428
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
2529
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
@@ -29,9 +33,13 @@ require (
2933
go.opentelemetry.io/otel/trace v1.39.0 // indirect
3034
golang.org/x/crypto v0.47.0 // indirect
3135
golang.org/x/net v0.49.0 // indirect
32-
golang.org/x/sys v0.40.0 // indirect
36+
golang.org/x/sys v0.42.0 // indirect
3337
golang.org/x/text v0.33.0 // indirect
3438
google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect
3539
google.golang.org/grpc v1.78.0 // indirect
3640
google.golang.org/protobuf v1.36.11 // indirect
41+
modernc.org/libc v1.70.0 // indirect
42+
modernc.org/mathutil v1.7.1 // indirect
43+
modernc.org/memory v1.11.0 // indirect
44+
modernc.org/sqlite v1.47.0 // indirect
3745
)

go.sum

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
88
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
99
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1010
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
11+
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
12+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
1113
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
1214
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
1315
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
@@ -35,8 +37,14 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
3537
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
3638
github.com/mark3labs/mcp-go v0.23.1 h1:RzTzZ5kJ+HxwnutKA4rll8N/pKV6Wh5dhCmiJUu5S9I=
3739
github.com/mark3labs/mcp-go v0.23.1/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
40+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
41+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
42+
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
43+
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
3844
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3945
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
46+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
47+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
4048
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
4149
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
4250
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
@@ -67,8 +75,11 @@ golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
6775
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
6876
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
6977
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
78+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7079
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
7180
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
81+
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
82+
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
7283
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
7384
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
7485
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
@@ -87,3 +98,11 @@ google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBN
8798
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
8899
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
89100
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
101+
modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw=
102+
modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo=
103+
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
104+
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
105+
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
106+
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
107+
modernc.org/sqlite v1.47.0 h1:R1XyaNpoW4Et9yly+I2EeX7pBza/w+pmYee/0HJDyKk=
108+
modernc.org/sqlite v1.47.0/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig=

internal/auth/auth.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ type Manager struct {
125125
oauthConfig *oauth2.Config
126126
// authMu prevents concurrent authentication attempts
127127
authMu sync.Mutex
128-
// AuthServerURL is set when the HTTP auth server is running (e.g. "http://localhost:8100/auth").
128+
// AuthServerURL is set when the HTTP auth server is running (e.g. "http://localhost:38917/auth").
129129
AuthServerURL string
130130
}
131131

@@ -192,7 +192,7 @@ func loadOAuthConfig() (*oauth2.Config, error) {
192192
}
193193

194194
// resolveOAuthPort determines the OAuth callback port.
195-
// Resolution order: GSUITE_MCP_OAUTH_PORT env var → config.json → default (8100).
195+
// Resolution order: GSUITE_MCP_OAUTH_PORT env var → config.json → default (38917).
196196
func resolveOAuthPort() (int, error) {
197197
if portStr := os.Getenv("GSUITE_MCP_OAUTH_PORT"); portStr != "" {
198198
port, err := strconv.Atoi(portStr)

internal/auth/server_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func newTestAuthServer() *AuthServer {
2424
Scopes: []string{"openid", "email"},
2525
},
2626
}
27-
return NewAuthServer(mgr, 8100)
27+
return NewAuthServer(mgr, 38917)
2828
}
2929

3030
func TestHandleAuth_RedirectsToGoogle(t *testing.T) {

0 commit comments

Comments
 (0)