{"_id":"@bdmarvin/typingmind-mcp","_rev":"8-4cd75b542eae2ac58e39239c22f4467c","name":"@bdmarvin/typingmind-mcp","dist-tags":{"latest":"1.1.17"},"versions":{"1.1.9":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.9","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"url":"forked from TypingMind","name":"Bdmarvin"},"license":"MIT","_id":"@bdmarvin/typingmind-mcp@1.1.9","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"bin":{"typingmind-mcp":"bin/index.js"},"dist":{"shasum":"dc98228db82204e3d81ffaf3411c3bd756c30f38","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.9.tgz","fileCount":10,"integrity":"sha512-EXhZ6PZ00Bjx5bWTh83uybyy75tDd7LIjUI1tm8U4MUFWsG1tJb9F8symC1rNW5Ds4uniXc+6V0nw961rHd3Sw==","signatures":[{"sig":"MEUCIQDY/VnMGmexuuLVmswWjjfB6WsyyRr1Bwgs+XzI/m7SeQIgMDOBGTfbay4L/+Ux0fQt6t8I6nu/27+aX0UGb4FE69I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37713},"main":"lib/server.js","engines":{"node":">=14.0.0"},"gitHead":"66195aa4a7789d6bc3ab53ab72054dc84f1240fa","scripts":{"start":"node bin/index.js"},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"repository":{"url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","directories":{},"_nodeVersion":"22.15.0","dependencies":{"cors":"^2.8.5","chalk":"^4.1.2","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1","@modelcontextprotocol/sdk":"^1.9.0","@google-cloud/secret-manager":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.5.3"},"_npmOperationalInternal":{"tmp":"tmp/typingmind-mcp_1.1.9_1748226360050_0.057077930319706205","host":"s3://npm-registry-packages-npm-production"}},"1.1.10":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.10","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"url":"forked from TypingMind","name":"Bdmarvin"},"license":"MIT","_id":"@bdmarvin/typingmind-mcp@1.1.10","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"bin":{"typingmind-mcp":"bin/index.js"},"dist":{"shasum":"a84e69c212b3d3c76f30b9730f9df6db4b829b69","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.10.tgz","fileCount":10,"integrity":"sha512-E5jsRRlm5ED0O6/F1oY8/4Gxm0mxf4SkxNz5nV/UIsXVlGI/3UMsaOmfZgfFknmzv4ZwxIWJbdxW/WuG0lkozA==","signatures":[{"sig":"MEUCIQCGeqeLmlpr1pGoqK43Chas/vQANE1ouewwfFxM1iJenAIgDqsbRBo56nMhakbM/QRhEDG8IWLlbDy2K+3Zb6rCUY8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37858},"main":"lib/server.js","engines":{"node":">=14.0.0"},"gitHead":"2f19eb38a50d1f7112edb502afeaf8675fd65c5a","scripts":{"start":"node bin/index.js"},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"repository":{"url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","directories":{},"_nodeVersion":"22.15.0","dependencies":{"cors":"^2.8.5","chalk":"^4.1.2","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1","@modelcontextprotocol/sdk":"^1.9.0","@google-cloud/secret-manager":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.5.3"},"_npmOperationalInternal":{"tmp":"tmp/typingmind-mcp_1.1.10_1748268583421_0.07784039856471736","host":"s3://npm-registry-packages-npm-production"}},"1.1.11":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.11","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"url":"forked from TypingMind","name":"Bdmarvin"},"license":"MIT","_id":"@bdmarvin/typingmind-mcp@1.1.11","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"bin":{"typingmind-mcp":"bin/index.js"},"dist":{"shasum":"2b9730457434bc590bcad7218a34ba4b5201514b","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.11.tgz","fileCount":8,"integrity":"sha512-4b6rqTK1Y0k9+VeMRdnMo7hb0XXslBqrMp9WTZofsqaAWkWSyEfksT6bncldllUy8zmWZAkS/+mrxCcoRtY4sw==","signatures":[{"sig":"MEQCIDPMPbq0kBV0vHSXmal5jbOZzJDzOuU8OwFuUIprO+j2AiA9VEbjWAsJiWFzS47lc61AZU0p0Tgi0y2YW3A1HJ9kyg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45798},"main":"lib/server.js","engines":{"node":">=14.0.0"},"gitHead":"a6e478c8918bdc3fcc671b08d9cd7633c1a170ee","scripts":{"start":"node bin/index.js"},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"repository":{"url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","directories":{},"_nodeVersion":"22.15.0","dependencies":{"cors":"^2.8.5","chalk":"^4.1.2","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1","@modelcontextprotocol/sdk":"^1.9.0","@google-cloud/secret-manager":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.5.3"},"_npmOperationalInternal":{"tmp":"tmp/typingmind-mcp_1.1.11_1748314778856_0.8436315754373744","host":"s3://npm-registry-packages-npm-production"}},"1.1.12":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.12","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"url":"forked from TypingMind","name":"Bdmarvin"},"license":"MIT","_id":"@bdmarvin/typingmind-mcp@1.1.12","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"bin":{"typingmind-mcp":"bin/index.js"},"dist":{"shasum":"7d099896d14a5e03fbfae2f2cf82e0f55d085b17","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.12.tgz","fileCount":8,"integrity":"sha512-9+WyWFAmwnirBmtUKSPaHFJ8Q7I7rOJ5nKkRE90LA73AAqAzdtBc6bcl8oo8ULwfLoZsxYrb9/S16uPXtkbd0g==","signatures":[{"sig":"MEUCICIl+ge9bJqP/t5yCbxpOi4njddZrXWn6wD1uHhpEPchAiEA8fQpFLBezAGrvb8aLLRAxZKF4vgUILivPPnSN14cw1E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45563},"main":"lib/server.js","engines":{"node":">=14.0.0"},"gitHead":"bbb4962db7e183b1d613e4f0d7a483fc2ff8f6c2","scripts":{"start":"node bin/index.js"},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"repository":{"url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","directories":{},"_nodeVersion":"22.15.0","dependencies":{"cors":"^2.8.5","chalk":"^4.1.2","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1","@modelcontextprotocol/sdk":"^1.9.0","@google-cloud/secret-manager":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.5.3"},"_npmOperationalInternal":{"tmp":"tmp/typingmind-mcp_1.1.12_1748316357209_0.3136955142174418","host":"s3://npm-registry-packages-npm-production"}},"1.1.13":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.13","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"url":"forked from TypingMind","name":"Bdmarvin"},"license":"MIT","_id":"@bdmarvin/typingmind-mcp@1.1.13","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"bin":{"typingmind-mcp":"bin/index.js"},"dist":{"shasum":"545538873333f9fa7a36bc9333d50bef2ce8dac3","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.13.tgz","fileCount":8,"integrity":"sha512-FjE56HEIRoChTRzcF+o7iQCOAWddX2ufFPWM7BdNq+0FL1DtKofaSsPw/0RcFEa5DT6vOR0ynasqf2syHBeY4Q==","signatures":[{"sig":"MEQCIBHc4QP5m7DhpQILc69jMrOEsu+Mzzb+hpFenzoU3Z7BAiBb5XrMKj+xeYOAbxtMv2dqCdMm9cG2RSIri8ZYe1TJlw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45568},"main":"lib/server.js","engines":{"node":">=14.0.0"},"gitHead":"50927c7d840e6a8c852f1c99f4d7427b8e4f1fae","scripts":{"start":"node bin/index.js"},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"repository":{"url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","directories":{},"_nodeVersion":"22.15.0","dependencies":{"cors":"^2.8.5","chalk":"^4.1.2","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1","@modelcontextprotocol/sdk":"^1.9.0","@google-cloud/secret-manager":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.5.3"},"_npmOperationalInternal":{"tmp":"tmp/typingmind-mcp_1.1.13_1748461284477_0.33544851269989273","host":"s3://npm-registry-packages-npm-production"}},"1.1.14":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.14","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"url":"forked from TypingMind","name":"Bdmarvin"},"license":"MIT","_id":"@bdmarvin/typingmind-mcp@1.1.14","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"bin":{"typingmind-mcp":"bin/index.js"},"dist":{"shasum":"aed693a3bccc5d61ffa57a399a2d703718479cda","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.14.tgz","fileCount":8,"integrity":"sha512-n/s1tNUgcpXSBO6H5pB3F+EMSca8YOJEq6TOcf6St5pk6UjWdkbcyWT0KkpBpC+dZ3ZkF1ThNpOZEPwao6yRXw==","signatures":[{"sig":"MEUCIQCv1U6UKGuZclTzJWvBwhYRZemmhEnjPEvQ3Y9zhxzlcQIgdBueCnEUZK8vfojg5sw5vQ+H51RHZ+rmsvOn0y93Rso=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45653},"main":"lib/server.js","engines":{"node":">=14.0.0"},"gitHead":"44c6369f82294821dc854066d76968270a0462b2","scripts":{"start":"node bin/index.js"},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"repository":{"url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","directories":{},"_nodeVersion":"22.15.0","dependencies":{"cors":"^2.8.5","chalk":"^4.1.2","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1","@modelcontextprotocol/sdk":"^1.9.0","@google-cloud/secret-manager":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.5.3"},"_npmOperationalInternal":{"tmp":"tmp/typingmind-mcp_1.1.14_1748569968556_0.5476560030446911","host":"s3://npm-registry-packages-npm-production"}},"1.1.15":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.15","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"url":"forked from TypingMind","name":"Bdmarvin"},"license":"MIT","_id":"@bdmarvin/typingmind-mcp@1.1.15","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"bin":{"typingmind-mcp":"bin/index.js"},"dist":{"shasum":"c8206f65cbdb50e0e483dd0f6d7eaf512f5d5f39","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.15.tgz","fileCount":8,"integrity":"sha512-FArO6ZYzhGdJmUXR8OjaT/zOF9AGGTJAXbDLyP7HG/AJ8UFU7Yv4qOapwLirR+XHC1j1scZPvb7RuTEuoKkUUg==","signatures":[{"sig":"MEUCIQDVXGvUqrsMVBvl/wRwiQg+uO5KH1hgUf/B0bioDUlemAIgP6FPpy6VEgEVaRfq+99mozYI+QvGNZaw8h34qZwMhcM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45645},"main":"lib/server.js","engines":{"node":">=14.0.0"},"gitHead":"4189c1ad9c5709214ad965c733b7be9bde465df6","scripts":{"start":"node bin/index.js"},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"repository":{"url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git","type":"git"},"_npmVersion":"10.9.2","description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","directories":{},"_nodeVersion":"22.15.0","dependencies":{"cors":"^2.8.5","chalk":"^4.1.2","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1","@modelcontextprotocol/sdk":"^1.9.0","@google-cloud/secret-manager":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"^3.5.3"},"_npmOperationalInternal":{"tmp":"tmp/typingmind-mcp_1.1.15_1748573650972_0.30585015024515005","host":"s3://npm-registry-packages-npm-production"}},"1.1.17":{"name":"@bdmarvin/typingmind-mcp","version":"1.1.17","repository":{"type":"git","url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git"},"description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","main":"lib/server.js","bin":{"typingmind-mcp":"bin/index.js"},"scripts":{"start":"node bin/index.js"},"keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"author":{"name":"Bdmarvin","url":"forked from TypingMind"},"license":"MIT","dependencies":{"@google-cloud/secret-manager":"^5.0.1","@modelcontextprotocol/sdk":"^1.9.0","chalk":"^4.1.2","cors":"^2.8.5","dotenv":"^16.3.1","express":"^4.18.2","googleapis":"^105.0.0","jsonwebtoken":"^9.0.2","json-stable-stringify":"^1.2.1"},"engines":{"node":">=14.0.0"},"devDependencies":{"prettier":"^3.5.3"},"_id":"@bdmarvin/typingmind-mcp@1.1.17","gitHead":"c3c06434be48aa1d0c063e8899e1a7196ad2fa25","bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","_nodeVersion":"22.15.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-E9FQBQNA919K3l4QpqjDYUNTj+QCj6n8FhlShggYMD1BgvFE+6YaQY1ln9Jt/2xJ5hOE7y1Qpapqdy2FgNTonA==","shasum":"64937a7feaf0a6a1d541e8f5c5d023982d36c1af","tarball":"https://registry.npmjs.org/@bdmarvin/typingmind-mcp/-/typingmind-mcp-1.1.17.tgz","fileCount":8,"unpackedSize":45758,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD/j2oieEKVth6va7LpFMdbDZg+CJJEHwR+NbMr/Bzd+QIgaaH7Ly4UvBpW9DlwsgeOFkzbnXj6kEa+AlOb5JleANo="}]},"_npmUser":{"name":"bdmarvin","email":"azrlmaster@gmail.com"},"directories":{},"maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/typingmind-mcp_1.1.17_1748809933523_0.09841953099256884"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-26T02:25:59.963Z","modified":"2025-06-01T20:32:13.888Z","1.1.9":"2025-05-26T02:26:00.240Z","1.1.10":"2025-05-26T14:09:43.627Z","1.1.11":"2025-05-27T02:59:39.047Z","1.1.12":"2025-05-27T03:25:57.388Z","1.1.13":"2025-05-28T19:41:24.653Z","1.1.14":"2025-05-30T01:52:48.762Z","1.1.15":"2025-05-30T02:54:11.183Z","1.1.17":"2025-06-01T20:32:13.705Z"},"bugs":{"url":"https://github.com/Bdmarvin1/typingmind-mcp/issues"},"author":{"name":"Bdmarvin","url":"forked from TypingMind"},"license":"MIT","homepage":"https://github.com/Bdmarvin1/typingmind-mcp#readme","keywords":["ai","mcp","model","context","protocol","typingmind","oauth","google auth"],"repository":{"type":"git","url":"git+https://github.com/Bdmarvin1/typingmind-mcp.git"},"description":"OAuth enabled Model Context Protocol (MCP) server runner (forked and enhanced by Bdmarvin from TypingMind/typingmind-mcp)","maintainers":[{"name":"bdmarvin","email":"azrlmaster@gmail.com"}],"readme":"# MCP OAuth Controller (formerly MCP Connector)\r\n\r\n**@bdmarvin/typingmind-mcp** is an enhanced server that runs and manages multiple Model Context Protocol (MCP) servers and now includes robust Google OAuth 2.0 integration. It acts as a central OAuth controller, allowing downstream MCP servers to securely access Google services (like Google Search Console) on behalf of a user. This project is a fork and modification of the original `@typingmind/mcp` connector.\r\n\r\nIt's designed for integration with clients like [TypingMind](https://www.typingmind.com/mcp) and enables secure, authenticated access to Google APIs for your custom AI models and tools.\r\n\r\n---\r\n\r\n## Key Features\r\n\r\n*   Manages multiple downstream MCP servers (e.g., started via STDIO).\r\n*   Acts as a central **Google OAuth 2.0 Controller**:\r\n    *   Handles the complete Google OAuth 2.0 Authorization Code flow.\r\n    *   Securely stores Google refresh tokens using **Google Secret Manager**.\r\n    *   Issues its own **User-Context MCP Token (JWT)** to represent an authenticated Google session.\r\n    *   Validates this User-Context MCP Token for requests requiring Google context.\r\n*   Dynamically provides fresh **Google Access Tokens** to downstream MCP servers when they need to call Google APIs.\r\n*   Existing MCP Connector functionalities (server management, tool calls) remain, now augmented with Google OAuth capabilities.\r\n*   Deployable via NPX, Docker, or directly on a server/Cloud Run.\r\n\r\n---\r\n\r\n## Setup and Configuration\r\n\r\n### 1. Prerequisites\r\n\r\n*   **Node.js:** Version 14 or later.\r\n*   **Google Cloud Project:**\r\n    *   Enable the **Secret Manager API**.\r\n    *   Enable APIs for the Google services you intend to use (e.g., \"Google Search Console API\").\r\n    *   Create **OAuth 2.0 Client ID credentials** (for \"Web application\"):\r\n        *   Note your `Client ID` and `Client Secret`.\r\n        *   Add **Authorized JavaScript origins** (e.g., `http://localhost:3000` for local dev, your Cloud Run URL `https://your-service.a.run.app`).\r\n        *   Add **Authorized redirect URIs**:\r\n            *   For local: `http://localhost:3000/oauth/google/callback` (adjust port if needed).\r\n            *   For Cloud Run: `https://your-service.a.run.app/oauth/google/callback`.\r\n    *   In **Secret Manager**, create a secret to store the Google refresh token (e.g., `typingmind-mcp-google-refresh-token`).\r\n*   **IAM Permissions:**\r\n    *   **For Local Development (using your user ADC - `gcloud auth application-default login`):** Your user account needs:\r\n        *   `Secret Manager Secret Accessor` role (to read the refresh token).\r\n        *   `Secret Manager Secret Version Adder` role (to store the refresh token).\r\n        *   Grant these preferably on the specific secret created above.\r\n    *   **For Cloud Run Deployment:** The **service account** used by your Cloud Run service needs the same roles (`Secret Manager Secret Accessor` and `Secret Manager Secret Version Adder`) on the secret.\r\n\r\n### 2. Environment Variables\r\n\r\nCreate a `.env` file in the project root for local development, or set these in your Cloud Run environment:\r\n\r\n```env\r\n# Main Server Authentication\r\nMCP_AUTH_TOKEN=your_strong_main_server_access_token\r\n\r\n# Google OAuth Client Credentials\r\nGOOGLE_CLIENT_ID=your_google_client_id_from_gcp_console\r\nGOOGLE_CLIENT_SECRET=your_google_client_secret_from_gcp_console\r\n\r\n# Google OAuth Redirect URI (MUST match one configured in GCP OAuth Client)\r\n# For local development (ensure port matches if you set PORT env var):\r\nGOOGLE_REDIRECT_URI=http://localhost:3000/oauth/google/callback\r\n# For Cloud Run (replace with your actual service URL):\r\n# GOOGLE_REDIRECT_URI=https://your-mcp-controller-url.a.run.app/oauth/google/callback\r\n\r\n# Google Cloud Project & Secret Manager\r\nGOOGLE_CLOUD_PROJECT=your_gcp_project_id_where_secret_lives\r\n# Full path to the secret for loading the latest version\r\nGOOGLE_REFRESH_TOKEN_SECRET_NAME_FOR_LOAD=projects/your_gcp_project_id/secrets/your_refresh_token_secret_id/versions/latest\r\n# Full parent path to the secret for storing new versions\r\nGOOGLE_REFRESH_TOKEN_SECRET_PARENT_FOR_STORE=projects/your_gcp_project_id/secrets/your_refresh_token_secret_id\r\n\r\n# User-Context MCP Token (JWT) Configuration\r\nMCP_USER_CONTEXT_JWT_SECRET=your_very_strong_random_secret_string_for_jwt_signing\r\nMCP_USER_CONTEXT_JWT_EXPIRES_IN=1h # Optional, defaults to 1 hour (e.g., 1h, 7d, 30m)\r\n\r\n# Optional Server Port (defaults to auto-discovery, e.g., 50880)\r\n# PORT=3000\r\n```\r\n\r\n**Note on `your_refresh_token_secret_id`:** This is the ID you gave the secret in Secret Manager (e.g., `typingmind-mcp-google-refresh-token`).\r\n\r\n### 3. Installation (if running from source)\r\n\r\n```bash\r\ngit clone https://github.com/Bdmarvin1/typingmind-mcp.git\r\ncd typingmind-mcp\r\ngit checkout building-oauth # Or your main working branch\r\npnpm install # or npm install\r\n# Ensure you have dotenv installed for local .env loading (pnpm add dotenv)\r\n# and require('dotenv').config() at the top of bin/index.js\r\n```\r\n\r\n---\r\n\r\n## How to Run\r\n\r\n### Running Locally (for Development/Testing)\r\n\r\n1.  Ensure your `.env` file is configured.\r\n2.  Make sure `require('dotenv').config();` is the first line in `bin/index.js`.\r\n3.  Start the server:\r\n    ```bash\r\n    # Pass the main auth token as an argument if not in .env as MCP_AUTH_TOKEN\r\n    pnpm start YOUR_MAIN_SERVER_AUTH_TOKEN\r\n    # Or, if MCP_AUTH_TOKEN is in your .env and bin/index.js is set up to read it:\r\n    # pnpm start\r\n    ```\r\n    The server will log the port it's running on.\r\n\r\n### Using NPX (for published package)\r\n\r\nOnce published to npm under `@bdmarvin/typingmind-mcp`:\r\n\r\n```bash\r\n# Ensure all required environment variables listed above are set in your shell\r\n# or in a .env file if you've modified bin/index.js to use dotenv.\r\nnpx @bdmarvin/typingmind-mcp YOUR_MAIN_SERVER_AUTH_TOKEN\r\n```\r\nOr, if `MCP_AUTH_TOKEN` is in the environment:\r\n```bash\r\nnpx @bdmarvin/typingmind-mcp\r\n```\r\n\r\n### HTTPS Support\r\n\r\nTo enable HTTPS, set the `CERTFILE` and `KEYFILE` environment variables with paths to your SSL certificate and private key files.\r\n\r\n---\r\n\r\n## Google OAuth Flow\r\n\r\n1.  **Initiate OAuth:**\r\n    Open your browser and navigate to `YOUR_SERVER_BASE_URL/oauth/google/initiate`.\r\n    *   Example (local): `http://localhost:3000/oauth/google/initiate`\r\n    *   Example (Cloud Run): `https://your-mcp-controller-url.a.run.app/oauth/google/initiate`\r\n\r\n2.  **Google Sign-in & Consent:**\r\n    You will be redirected to Google. Sign in with the Google account that has access to the services you want this controller to manage (e.g., Google Search Console). Grant the requested permissions.\r\n\r\n3.  **Callback & Token Generation:**\r\n    Google will redirect back to your server's `/oauth/google/callback` URI.\r\n    Your server will:\r\n    *   Exchange the Google authorization code for Google access and refresh tokens.\r\n    *   Securely store the Google refresh token in Google Secret Manager.\r\n    *   Generate a **`user_context_mcp_token` (JWT)**.\r\n    *   Return a JSON response containing this `user_context_mcp_token`.\r\n\r\n    **Example JSON Response from `/oauth/google/callback`:**\r\n    ```json\r\n    {\r\n      \"message\": \"Google OAuth successful. ... User-Context MCP Token issued.\",\r\n      \"user_context_mcp_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0...\",\r\n      \"google_access_token_exists\": true,\r\n      \"oauth_client_has_refresh_token\": true\r\n    }\r\n    ```\r\n\r\n4.  **Using the `user_context_mcp_token`:**\r\n    *   The client application (e.g., TypingMind, or a tool like Postman/curl for testing) needs to store this `user_context_mcp_token`.\r\n    *   For subsequent requests to this MCP OAuth Controller that require Google-authenticated actions (specifically to the `/clients/:id/call_tools` endpoint), the client **must** send this token in the `X-User-Context-MCP-Token` header.\r\n        Example Header: `X-User-Context-MCP-Token: eyJhbGciOiJIUzI1NiIsI...`\r\n\r\n---\r\n\r\n## Interaction with Downstream MCP Servers\r\n\r\nWhen this OAuth Controller calls a tool on a downstream MCP server (managed via STDIO, like the `@bdmarvin/mcp-server-gsc`):\r\n\r\n1.  The incoming request to `/clients/:id/call_tools` must be authenticated with both the main server `authToken` (in `Authorization: Bearer`) AND the `user_context_mcp_token` (in `X-User-Context-MCP-Token`).\r\n2.  The OAuth Controller validates both tokens.\r\n3.  It uses its stored Google refresh token (associated with the user context from the JWT) to obtain a fresh Google Access Token.\r\n4.  This Google Access Token, along with Google User ID and Email, are injected into the `arguments` object passed to the downstream MCP server's tool:\r\n    *   `arguments.__google_access_token__`\r\n    *   `arguments.__google_user_id__`\r\n    *   `arguments.__google_user_email__`\r\n5.  The downstream MCP server (e.g., `@bdmarvin/mcp-server-gsc`) must be designed to extract these from the arguments and use the `__google_access_token__` to make its API calls to Google services.\r\n\r\n---\r\n\r\n## Deploying to Google Cloud Run\r\n\r\n1.  **Dockerfile:** A `Dockerfile` is included in the repository.\r\n2.  **Build & Push Image:**\r\n    Use Google Cloud Build to build the container image and push it to Google Artifact Registry (or Container Registry). Example `cloudbuild.yaml` might be needed.\r\n    ```bash\r\n    gcloud builds submit --tag gcr.io/YOUR_GCP_PROJECT_ID/mcp-oauth-controller:latest .\r\n    ```\r\n3.  **Deploy Service to Cloud Run:**\r\n    ```bash\r\n    gcloud run deploy mcp-oauth-controller-service \\\r\n      --image gcr.io/YOUR_GCP_PROJECT_ID/mcp-oauth-controller:latest \\\r\n      --platform managed \\\r\n      --region YOUR_REGION \\\r\n      --allow-unauthenticated \\ # Or configure IAM for authenticated invocation\r\n      --service-account YOUR_CLOUD_RUN_SERVICE_ACCOUNT_EMAIL \\\r\n      --port CONTAINER_PORT # e.g., 8080, which the Dockerfile EXPOSEs\r\n      # Set all required environment variables (see \"Environment Variables\" section)\r\n      # For sensitive variables (GOOGLE_CLIENT_SECRET, MCP_AUTH_TOKEN, MCP_USER_CONTEXT_JWT_SECRET),\r\n      # create them as secrets in Secret Manager and link them in Cloud Run:\r\n      # --set-secrets=GOOGLE_CLIENT_SECRET=your-gcp-secret-name:latest,MCP_AUTH_TOKEN=your-mcp-auth-token-secret:latest,...\r\n    ```\r\n    Ensure the `GOOGLE_REDIRECT_URI` environment variable for the Cloud Run service points to its own public HTTPS URL + `/oauth/google/callback`.\r\n4.  **Service Account Permissions:** The Cloud Run service account needs `Secret Manager Secret Accessor` and `Secret Manager Secret Version Adder` roles for the Google refresh token secret.\r\n\r\n---\r\n\r\n## API Endpoints\r\n\r\nAll API endpoints (unless specified otherwise) require authentication via the main Bearer token (`Authorization: Bearer <MCP_AUTH_TOKEN>`).\r\n\r\n| Endpoint                       | Method | Auth Required | User Context Token Required? | Description                                      |\r\n|---------------------------------|--------|---------------|------------------------------|--------------------------------------------------|\r\n| `/oauth/google/initiate`       | GET    | No            | No                           | Starts Google OAuth flow.                        |\r\n| `/oauth/google/callback`       | GET    | No            | No                           | Handles Google OAuth callback, issues User-Context MCP Token. |\r\n| `/ping`                        | GET    | Main Token    | No                           | Health check.                                    |\r\n| `/test-user-context`           | GET    | Main Token    | Yes (`X-User-Context-MCP-Token`) | Tests User-Context MCP Token validation.         |\r\n| `/start`                       | POST   | Main Token    | No                           | Start downstream MCP clients.                    |\r\n| `/restart/:id`                 | POST   | Main Token    | No                           | Restart a specific client.                       |\r\n| `/clients`                     | GET    | Main Token    | No                           | List running MCP clients.                        |\r\n| `/clients/:id`                 | GET    | Main Token    | No                           | Get info for a specific client.                  |\r\n| `/clients/:id/tools`           | GET    | Main Token    | No                           | List tools for a client.                         |\r\n| `/clients/:id/call_tools`      | POST   | Main Token    | Yes (`X-User-Context-MCP-Token`) | Call a tool; injects Google tokens for downstream. |\r\n| `/clients/:id`                 | DELETE | Main Token    | No                           | Stop and delete a client.                        |\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}