Spaces:
Sleeping
Sleeping
File size: 5,715 Bytes
7dc28be | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | # Contributing
Thanks for your interest in contributing! This guide covers how to set up the project for local development, understand the architecture, and submit changes.
## Development Setup
### Prerequisites
- Node.js 20+ ([nodejs.org](https://nodejs.org/))
- Git ([git-scm.com](https://git-scm.com/downloads))
- A Google Account with access to test documents
### Clone and Build
```bash
git clone https://github.com/a-bonus/google-docs-mcp.git
cd google-docs-mcp
npm install
npm run build
```
### Authenticate
You need Google OAuth credentials to test the server against real APIs.
**Option A: credentials.json file**
1. Download your OAuth client JSON from [Google Cloud Console](https://console.cloud.google.com/)
2. Rename it to `credentials.json` and place it in the project root
3. Run `npm start auth` to open the browser-based OAuth flow
**Option B: Environment variables**
```bash
GOOGLE_CLIENT_ID="your-client-id" \
GOOGLE_CLIENT_SECRET="your-client-secret" \
npm start auth
```
Both options save the refresh token to `~/.config/google-docs-mcp/token.json`. OAuth client IDs and client secrets stay in your environment or `credentials.json`; they are not stored in the token file.
### Register Your Local Build
Point your MCP client at the local build for testing:
```json
{
"mcpServers": {
"google-docs": {
"command": "node",
"args": ["/absolute/path/to/mcp-googledocs-server/dist/index.js"]
}
}
}
```
### Scripts
| Command | Description |
| ---------------------- | ------------------------------ |
| `npm start` | Start the MCP server |
| `npm start auth` | Run the interactive OAuth flow |
| `npm run build` | Compile TypeScript to `dist/` |
| `npm test` | Run tests (Vitest) |
| `npm run format` | Format code with Prettier |
| `npm run format:check` | Check formatting |
---
## Project Architecture
### Entry Points
```
src/index.ts Entry point: CLI (auth subcommand) and MCP server startup
src/auth.ts OAuth / service account authentication
src/clients.ts Google API client singletons (Docs, Drive, Sheets)
```
### Tools
Tools live in `src/tools/`, organized by domain. Each tool is a single file exporting a `register(server: FastMCP)` function.
```
src/tools/
βββ index.ts Top-level router
βββ docs/ Google Docs tools (13)
β βββ comments/ Comment management (6)
β βββ formatting/ Text and paragraph styling (2)
βββ drive/ Google Drive tools (15)
βββ sheets/ Google Sheets tools (37)
βββ gmail/ Gmail tools (13)
βββ calendar/ Google Calendar tools (5)
βββ utils/ Cross-cutting utilities (3)
```
### Helpers
| File | Purpose |
| ------------------------------- | ------------------------------------------------------------------ |
| `src/googleDocsApiHelpers.ts` | Text range finding, batch update execution, style request builders |
| `src/googleSheetsApiHelpers.ts` | A1 notation parsing, cell formatting, freeze, validation |
| `src/markdown-transformer/` | Markdown parsing and bidirectional Google Docs conversion |
| `src/types.ts` | Zod schemas, hex color validation, shared type definitions |
| `src/logger.ts` | Leveled logger (debug/info/warn/error) writing to stderr |
### Authentication Flow
The auth module (`src/auth.ts`) resolves credentials in this order:
1. `SERVICE_ACCOUNT_PATH` env var -- service account JWT
2. `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` env vars -- OAuth (for `npx` consumers)
3. `credentials.json` in the project root -- OAuth (for local dev)
Tokens are persisted to `~/.config/google-docs-mcp/token.json` (respects `XDG_CONFIG_HOME`). The token file stores OAuth token credentials only, not OAuth client IDs or client secrets.
---
## Adding a New Tool
1. Create a new file in the appropriate domain folder (e.g., `src/tools/sheets/myNewTool.ts`)
2. Export a `register(server: FastMCP)` function that calls `server.addTool({...})`
3. Import and call it from the domain's `index.ts` router
4. Add tests if the tool involves non-trivial logic
### Tool Conventions
- **Names:** camelCase, verb-first (e.g., `readDocument`, `formatCells`)
- **Descriptions:** Start with what the tool does, mention when to use it, note any caveats
- **Parameters:** Use Zod schemas with `.describe()` on every field
- **Errors:** Throw `UserError` from `fastmcp` for user-facing errors
- **Output:** Return `JSON.stringify`'d structured data for tools that return actionable information
---
## Testing
Tests use [Vitest](https://vitest.dev/) and live alongside source files or in `src/`:
```bash
npm test # Run all tests
npm test -- --watch # Watch mode
```
Tests mock Google API clients -- they don't make real API calls.
---
## Code Style
- TypeScript with strict mode
- ESM modules (`.js` extensions in imports)
- Prettier for formatting (`npm run format`)
- All log output goes to stderr (stdout is reserved for MCP protocol)
---
## Releasing
Releases are automated via GitHub Actions. To publish a new version:
1. Update the version in `package.json`
2. Commit and push to `main`
3. Tag the commit: `git tag v1.2.3 && git push origin v1.2.3`
4. The [release workflow](.github/workflows/release.yml) will run CI checks, publish to npm, and create a GitHub Release
The npm package is published as `@a-bonus/google-docs-mcp`.
|