mcp-google-multi 6.0.0-beta.5 → 6.0.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,8 +28,9 @@ export declare function transportIncludesHttp(t: Transport): boolean;
28
28
  export declare function resolveTransport(env?: NodeJS.ProcessEnv): Transport;
29
29
  /**
30
30
  * Canonicalize a public base URL. WHATWG `URL` already lowercases the
31
- * scheme+host and omits a default port from `.host`; this adds the HTTPS-only
32
- * scheme check, strips fragment/query/userinfo, and removes a trailing slash.
31
+ * scheme+host and omits a default port from `.host`; this restricts the scheme
32
+ * to http(s), strips fragment/query/userinfo, and removes a trailing slash.
33
+ * `http:` stays accepted for a loopback single-owner setup (docs/internals.md).
33
34
  */
34
35
  export declare function canonicalizePublicUrl(raw: string): string;
35
36
  export declare function resolveHttpConfig(env?: NodeJS.ProcessEnv): HttpConfig;
@@ -27,8 +27,9 @@ export function resolveTransport(env = process.env) {
27
27
  }
28
28
  /**
29
29
  * Canonicalize a public base URL. WHATWG `URL` already lowercases the
30
- * scheme+host and omits a default port from `.host`; this adds the HTTPS-only
31
- * scheme check, strips fragment/query/userinfo, and removes a trailing slash.
30
+ * scheme+host and omits a default port from `.host`; this restricts the scheme
31
+ * to http(s), strips fragment/query/userinfo, and removes a trailing slash.
32
+ * `http:` stays accepted for a loopback single-owner setup (docs/internals.md).
32
33
  */
33
34
  export function canonicalizePublicUrl(raw) {
34
35
  let u;
@@ -143,6 +143,18 @@ export function denyReason(tool, policy) {
143
143
  }
144
144
  return { rule: 'profile', profile: policy.profile };
145
145
  }
146
+ const CUD_CLASSES = ['read', 'create', 'update', 'delete'];
147
+ // The allow-list vocabulary is service:cud or service:op, never the tool
148
+ // name, so suggesting the name would hand back a pattern that never matches.
149
+ function allowSuggestion(tool) {
150
+ const op = opOf(tool);
151
+ const pattern = `${tool.service}:${op}`;
152
+ // An op spelled like a cud class (drive_update) is also that class's pattern.
153
+ if (CUD_CLASSES.includes(op)) {
154
+ return `allow it with GOOGLE_WRITE_ALLOW="${pattern}", which also allows every other ${op}-class ${tool.service} tool`;
155
+ }
156
+ return `allow just this one with GOOGLE_WRITE_ALLOW="${pattern}"`;
157
+ }
146
158
  function denyHint(tool, reason) {
147
159
  if (reason.rule === 'read_only') {
148
160
  return 'GOOGLE_READ_ONLY=true refuses every write, ahead of the profile and the allow-list, so neither of those can enable this. Unset GOOGLE_READ_ONLY to allow writes.';
@@ -154,15 +166,13 @@ function denyHint(tool, reason) {
154
166
  const what = reason.kind === 'push_registration'
155
167
  ? 'registers a push channel, which sends this account\'s activity to an external URL'
156
168
  : 'needs a scope that acts on the whole organization, on legal holds, on billing, or on deployed code';
157
- return `"${tool.name}" ${what}, so "${reason.profile}" refuses it whatever its verb. Use GOOGLE_PROFILE=full-writes, or allow just this one with GOOGLE_WRITE_ALLOW="${tool.service}:${opOf(tool)}".`;
169
+ return `"${tool.name}" ${what}, so "${reason.profile}" refuses it whatever its verb. Use GOOGLE_PROFILE=full-writes, or ${allowSuggestion(tool)}.`;
158
170
  }
159
171
  const usable = profilesAllowing(tool).filter((p) => p !== reason.profile);
160
172
  const profiles = usable.length > 0
161
173
  ? `Use GOOGLE_PROFILE=${usable.join(' or ')}`
162
174
  : 'No profile permits this operation';
163
- // The allow-list vocabulary is service:cud or service:op, never the tool
164
- // name, so suggesting the name would hand back a pattern that never matches.
165
- return `Profile "${reason.profile}" does not permit ${tool.cud}. ${profiles}, or allow just this one with GOOGLE_WRITE_ALLOW="${tool.service}:${opOf(tool)}".`;
175
+ return `Profile "${reason.profile}" does not permit ${tool.cud}. ${profiles}, or ${allowSuggestion(tool)}.`;
166
176
  }
167
177
  export function writeDisabledResult(tool, policy, account) {
168
178
  // Recomputed rather than passed in: every call site has already run
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-google-multi",
3
- "version": "6.0.0-beta.5",
3
+ "version": "6.0.1-alpha.1",
4
4
  "mcpName": "io.github.bakissation/mcp-google-multi",
5
5
  "description": "Local MCP server for Google Workspace (Gmail, Drive, Calendar, Sheets, Docs, Contacts, Tasks, Meet, Search Console, +Forms/Chat/Admin) across multiple accounts — OAuth-only, encrypted token storage, deny-by-default writes.",
6
6
  "type": "module",