gcs-google-mcp-server 0.1.0
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.
- package/README.md +241 -0
- package/build/index.integration-with-mock.js +42 -0
- package/build/index.js +152 -0
- package/package.json +50 -0
- package/shared/gcs-client/gcs-client.d.ts +74 -0
- package/shared/gcs-client/gcs-client.integration-mock.d.ts +15 -0
- package/shared/gcs-client/gcs-client.integration-mock.js +131 -0
- package/shared/gcs-client/gcs-client.js +120 -0
- package/shared/index.d.ts +8 -0
- package/shared/index.js +9 -0
- package/shared/logging.d.ts +24 -0
- package/shared/logging.js +40 -0
- package/shared/resources.d.ts +3 -0
- package/shared/resources.js +65 -0
- package/shared/server.d.ts +46 -0
- package/shared/server.js +37 -0
- package/shared/state.d.ts +43 -0
- package/shared/state.js +67 -0
- package/shared/tools/copy-object.d.ts +59 -0
- package/shared/tools/copy-object.js +71 -0
- package/shared/tools/create-bucket.d.ts +45 -0
- package/shared/tools/create-bucket.js +82 -0
- package/shared/tools/delete-bucket.d.ts +38 -0
- package/shared/tools/delete-bucket.js +60 -0
- package/shared/tools/delete-object.d.ts +45 -0
- package/shared/tools/delete-object.js +64 -0
- package/shared/tools/get-object.d.ts +45 -0
- package/shared/tools/get-object.js +65 -0
- package/shared/tools/head-bucket.d.ts +38 -0
- package/shared/tools/head-bucket.js +58 -0
- package/shared/tools/list-buckets.d.ts +27 -0
- package/shared/tools/list-buckets.js +49 -0
- package/shared/tools/list-objects.d.ts +68 -0
- package/shared/tools/list-objects.js +80 -0
- package/shared/tools/put-object.d.ts +69 -0
- package/shared/tools/put-object.js +81 -0
- package/shared/tools.d.ts +30 -0
- package/shared/tools.js +154 -0
- package/shared/types.d.ts +1 -0
- package/shared/types.js +6 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const ListBucketsSchema = z.object({});
|
|
3
|
+
export function listBucketsTool(_server, clientFactory) {
|
|
4
|
+
return {
|
|
5
|
+
name: 'list_buckets',
|
|
6
|
+
description: `List all GCS buckets in the Google Cloud project.
|
|
7
|
+
|
|
8
|
+
Returns a list of bucket names and their creation dates.
|
|
9
|
+
|
|
10
|
+
Example response:
|
|
11
|
+
{
|
|
12
|
+
"buckets": [
|
|
13
|
+
{"name": "my-app-data", "creationDate": "2024-01-15T10:30:00Z"},
|
|
14
|
+
{"name": "logs-archive", "creationDate": "2024-02-20T14:45:00Z"}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
Use cases:
|
|
19
|
+
- Discover available buckets in the project
|
|
20
|
+
- Audit bucket inventory
|
|
21
|
+
- Find bucket names for subsequent operations`,
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {},
|
|
25
|
+
required: [],
|
|
26
|
+
},
|
|
27
|
+
handler: async (_args) => {
|
|
28
|
+
try {
|
|
29
|
+
const client = clientFactory();
|
|
30
|
+
const result = await client.listBuckets();
|
|
31
|
+
return {
|
|
32
|
+
content: [
|
|
33
|
+
{
|
|
34
|
+
type: 'text',
|
|
35
|
+
text: JSON.stringify(result, null, 2),
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
return {
|
|
43
|
+
content: [{ type: 'text', text: `Error listing buckets: ${message}` }],
|
|
44
|
+
isError: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import type { GCSClientFactory } from '../server.js';
|
|
4
|
+
export declare const ListObjectsSchema: z.ZodObject<{
|
|
5
|
+
bucket: z.ZodString;
|
|
6
|
+
prefix: z.ZodOptional<z.ZodString>;
|
|
7
|
+
maxResults: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
pageToken: z.ZodOptional<z.ZodString>;
|
|
9
|
+
delimiter: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
bucket: string;
|
|
12
|
+
prefix?: string | undefined;
|
|
13
|
+
maxResults?: number | undefined;
|
|
14
|
+
pageToken?: string | undefined;
|
|
15
|
+
delimiter?: string | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
bucket: string;
|
|
18
|
+
prefix?: string | undefined;
|
|
19
|
+
maxResults?: number | undefined;
|
|
20
|
+
pageToken?: string | undefined;
|
|
21
|
+
delimiter?: string | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function listObjectsTool(_server: Server, clientFactory: GCSClientFactory): {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: "object";
|
|
28
|
+
properties: {
|
|
29
|
+
bucket: {
|
|
30
|
+
type: string;
|
|
31
|
+
description: "The name of the GCS bucket (e.g., \"my-app-data\")";
|
|
32
|
+
};
|
|
33
|
+
prefix: {
|
|
34
|
+
type: string;
|
|
35
|
+
description: "Filter objects by key prefix (e.g., \"logs/2024/\" to list only objects in that folder)";
|
|
36
|
+
};
|
|
37
|
+
maxResults: {
|
|
38
|
+
type: string;
|
|
39
|
+
minimum: number;
|
|
40
|
+
maximum: number;
|
|
41
|
+
description: "Maximum number of objects to return (1-1000, default: 1000)";
|
|
42
|
+
};
|
|
43
|
+
pageToken: {
|
|
44
|
+
type: string;
|
|
45
|
+
description: "Token for pagination, returned from previous list request when truncated";
|
|
46
|
+
};
|
|
47
|
+
delimiter: {
|
|
48
|
+
type: string;
|
|
49
|
+
description: "Character to group keys (e.g., \"/\" to simulate folders). Common prefixes are returned separately.";
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
required: string[];
|
|
53
|
+
};
|
|
54
|
+
handler: (args: unknown) => Promise<{
|
|
55
|
+
content: {
|
|
56
|
+
type: string;
|
|
57
|
+
text: string;
|
|
58
|
+
}[];
|
|
59
|
+
isError?: undefined;
|
|
60
|
+
} | {
|
|
61
|
+
content: {
|
|
62
|
+
type: string;
|
|
63
|
+
text: string;
|
|
64
|
+
}[];
|
|
65
|
+
isError: boolean;
|
|
66
|
+
}>;
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=list-objects.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const PARAM_DESCRIPTIONS = {
|
|
3
|
+
bucket: 'The name of the GCS bucket (e.g., "my-app-data")',
|
|
4
|
+
prefix: 'Filter objects by key prefix (e.g., "logs/2024/" to list only objects in that folder)',
|
|
5
|
+
maxResults: 'Maximum number of objects to return (1-1000, default: 1000)',
|
|
6
|
+
pageToken: 'Token for pagination, returned from previous list request when truncated',
|
|
7
|
+
delimiter: 'Character to group keys (e.g., "/" to simulate folders). Common prefixes are returned separately.',
|
|
8
|
+
};
|
|
9
|
+
export const ListObjectsSchema = z.object({
|
|
10
|
+
bucket: z.string().min(1).describe(PARAM_DESCRIPTIONS.bucket),
|
|
11
|
+
prefix: z.string().optional().describe(PARAM_DESCRIPTIONS.prefix),
|
|
12
|
+
maxResults: z.number().min(1).max(1000).optional().describe(PARAM_DESCRIPTIONS.maxResults),
|
|
13
|
+
pageToken: z.string().optional().describe(PARAM_DESCRIPTIONS.pageToken),
|
|
14
|
+
delimiter: z.string().optional().describe(PARAM_DESCRIPTIONS.delimiter),
|
|
15
|
+
});
|
|
16
|
+
export function listObjectsTool(_server, clientFactory) {
|
|
17
|
+
return {
|
|
18
|
+
name: 'list_objects',
|
|
19
|
+
description: `List objects in a GCS bucket with optional prefix filtering and pagination.
|
|
20
|
+
|
|
21
|
+
Example response:
|
|
22
|
+
{
|
|
23
|
+
"objects": [
|
|
24
|
+
{"key": "data/file1.json", "size": 1234, "lastModified": "2024-03-01T10:00:00Z"},
|
|
25
|
+
{"key": "data/file2.json", "size": 5678, "lastModified": "2024-03-02T11:00:00Z"}
|
|
26
|
+
],
|
|
27
|
+
"commonPrefixes": ["data/subdir/"],
|
|
28
|
+
"isTruncated": false
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Use cases:
|
|
32
|
+
- Browse bucket contents
|
|
33
|
+
- Find files matching a prefix pattern
|
|
34
|
+
- List "folders" using delimiter
|
|
35
|
+
- Paginate through large buckets`,
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
bucket: { type: 'string', description: PARAM_DESCRIPTIONS.bucket },
|
|
40
|
+
prefix: { type: 'string', description: PARAM_DESCRIPTIONS.prefix },
|
|
41
|
+
maxResults: {
|
|
42
|
+
type: 'number',
|
|
43
|
+
minimum: 1,
|
|
44
|
+
maximum: 1000,
|
|
45
|
+
description: PARAM_DESCRIPTIONS.maxResults,
|
|
46
|
+
},
|
|
47
|
+
pageToken: { type: 'string', description: PARAM_DESCRIPTIONS.pageToken },
|
|
48
|
+
delimiter: { type: 'string', description: PARAM_DESCRIPTIONS.delimiter },
|
|
49
|
+
},
|
|
50
|
+
required: ['bucket'],
|
|
51
|
+
},
|
|
52
|
+
handler: async (args) => {
|
|
53
|
+
try {
|
|
54
|
+
const validated = ListObjectsSchema.parse(args);
|
|
55
|
+
const client = clientFactory();
|
|
56
|
+
const result = await client.listObjects(validated.bucket, {
|
|
57
|
+
prefix: validated.prefix,
|
|
58
|
+
maxResults: validated.maxResults,
|
|
59
|
+
pageToken: validated.pageToken,
|
|
60
|
+
delimiter: validated.delimiter,
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
type: 'text',
|
|
66
|
+
text: JSON.stringify(result, null, 2),
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: 'text', text: `Error listing objects: ${message}` }],
|
|
75
|
+
isError: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import type { GCSClientFactory } from '../server.js';
|
|
4
|
+
export declare const PutObjectSchema: z.ZodObject<{
|
|
5
|
+
bucket: z.ZodString;
|
|
6
|
+
key: z.ZodString;
|
|
7
|
+
content: z.ZodString;
|
|
8
|
+
contentType: z.ZodOptional<z.ZodString>;
|
|
9
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
content: string;
|
|
12
|
+
bucket: string;
|
|
13
|
+
key: string;
|
|
14
|
+
metadata?: Record<string, string> | undefined;
|
|
15
|
+
contentType?: string | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
content: string;
|
|
18
|
+
bucket: string;
|
|
19
|
+
key: string;
|
|
20
|
+
metadata?: Record<string, string> | undefined;
|
|
21
|
+
contentType?: string | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function putObjectTool(_server: Server, clientFactory: GCSClientFactory): {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: "object";
|
|
28
|
+
properties: {
|
|
29
|
+
bucket: {
|
|
30
|
+
type: string;
|
|
31
|
+
description: "The name of the GCS bucket (e.g., \"my-app-data\")";
|
|
32
|
+
};
|
|
33
|
+
key: {
|
|
34
|
+
type: string;
|
|
35
|
+
description: "The object key (path) within the bucket (e.g., \"data/config.json\")";
|
|
36
|
+
};
|
|
37
|
+
content: {
|
|
38
|
+
type: string;
|
|
39
|
+
description: "The content to store in the object (text/string data)";
|
|
40
|
+
};
|
|
41
|
+
contentType: {
|
|
42
|
+
type: string;
|
|
43
|
+
description: "MIME type of the content (e.g., \"application/json\", \"text/plain\"). Defaults to \"text/plain\".";
|
|
44
|
+
};
|
|
45
|
+
metadata: {
|
|
46
|
+
type: string;
|
|
47
|
+
additionalProperties: {
|
|
48
|
+
type: string;
|
|
49
|
+
};
|
|
50
|
+
description: "Custom metadata as key-value pairs (e.g., {\"author\": \"system\", \"version\": \"1.0\"})";
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
required: string[];
|
|
54
|
+
};
|
|
55
|
+
handler: (args: unknown) => Promise<{
|
|
56
|
+
content: {
|
|
57
|
+
type: string;
|
|
58
|
+
text: string;
|
|
59
|
+
}[];
|
|
60
|
+
isError?: undefined;
|
|
61
|
+
} | {
|
|
62
|
+
content: {
|
|
63
|
+
type: string;
|
|
64
|
+
text: string;
|
|
65
|
+
}[];
|
|
66
|
+
isError: boolean;
|
|
67
|
+
}>;
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=put-object.d.ts.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const PARAM_DESCRIPTIONS = {
|
|
3
|
+
bucket: 'The name of the GCS bucket (e.g., "my-app-data")',
|
|
4
|
+
key: 'The object key (path) within the bucket (e.g., "data/config.json")',
|
|
5
|
+
content: 'The content to store in the object (text/string data)',
|
|
6
|
+
contentType: 'MIME type of the content (e.g., "application/json", "text/plain"). Defaults to "text/plain".',
|
|
7
|
+
metadata: 'Custom metadata as key-value pairs (e.g., {"author": "system", "version": "1.0"})',
|
|
8
|
+
};
|
|
9
|
+
export const PutObjectSchema = z.object({
|
|
10
|
+
bucket: z.string().min(1).describe(PARAM_DESCRIPTIONS.bucket),
|
|
11
|
+
key: z.string().min(1).describe(PARAM_DESCRIPTIONS.key),
|
|
12
|
+
content: z.string().describe(PARAM_DESCRIPTIONS.content),
|
|
13
|
+
contentType: z.string().optional().describe(PARAM_DESCRIPTIONS.contentType),
|
|
14
|
+
metadata: z.record(z.string()).optional().describe(PARAM_DESCRIPTIONS.metadata),
|
|
15
|
+
});
|
|
16
|
+
export function putObjectTool(_server, clientFactory) {
|
|
17
|
+
return {
|
|
18
|
+
name: 'put_object',
|
|
19
|
+
description: `Upload or update an object in GCS.
|
|
20
|
+
|
|
21
|
+
Creates a new object or overwrites an existing one with the provided content.
|
|
22
|
+
|
|
23
|
+
Example response:
|
|
24
|
+
{
|
|
25
|
+
"etag": "\\"abc123def456\\"",
|
|
26
|
+
"generation": "1234567890"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Use cases:
|
|
30
|
+
- Store configuration files
|
|
31
|
+
- Upload JSON data
|
|
32
|
+
- Create text files
|
|
33
|
+
- Save generated content
|
|
34
|
+
|
|
35
|
+
Note: This tool handles text content. For binary files, use base64 encoding or a different approach.`,
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
bucket: { type: 'string', description: PARAM_DESCRIPTIONS.bucket },
|
|
40
|
+
key: { type: 'string', description: PARAM_DESCRIPTIONS.key },
|
|
41
|
+
content: { type: 'string', description: PARAM_DESCRIPTIONS.content },
|
|
42
|
+
contentType: { type: 'string', description: PARAM_DESCRIPTIONS.contentType },
|
|
43
|
+
metadata: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
additionalProperties: { type: 'string' },
|
|
46
|
+
description: PARAM_DESCRIPTIONS.metadata,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ['bucket', 'key', 'content'],
|
|
50
|
+
},
|
|
51
|
+
handler: async (args) => {
|
|
52
|
+
try {
|
|
53
|
+
const validated = PutObjectSchema.parse(args);
|
|
54
|
+
const client = clientFactory();
|
|
55
|
+
const result = await client.putObject(validated.bucket, validated.key, validated.content, {
|
|
56
|
+
contentType: validated.contentType,
|
|
57
|
+
metadata: validated.metadata,
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: 'text',
|
|
63
|
+
text: JSON.stringify({
|
|
64
|
+
success: true,
|
|
65
|
+
message: `Object uploaded to gs://${validated.bucket}/${validated.key}`,
|
|
66
|
+
...result,
|
|
67
|
+
}, null, 2),
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
74
|
+
return {
|
|
75
|
+
content: [{ type: 'text', text: `Error putting object: ${message}` }],
|
|
76
|
+
isError: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { GCSClientFactory } from './server.js';
|
|
3
|
+
/**
|
|
4
|
+
* Available tool groups for GCS operations.
|
|
5
|
+
* - 'readonly': Read-only operations (list, get, head)
|
|
6
|
+
* - 'readwrite': Write operations (put, copy, delete, create)
|
|
7
|
+
*/
|
|
8
|
+
export type ToolGroup = 'readonly' | 'readwrite';
|
|
9
|
+
/**
|
|
10
|
+
* Parse enabled tool groups from environment variable.
|
|
11
|
+
* @param enabledGroupsParam - Comma-separated list of groups (e.g., "readonly,readwrite")
|
|
12
|
+
* @returns Array of enabled tool groups
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseEnabledToolGroups(enabledGroupsParam?: string): ToolGroup[];
|
|
15
|
+
/**
|
|
16
|
+
* Parse enabled/disabled tools from environment variables.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseToolFilters(enabledToolsParam?: string, disabledToolsParam?: string): {
|
|
19
|
+
enabledTools: Set<string> | null;
|
|
20
|
+
disabledTools: Set<string>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Get all tool names for documentation/help purposes.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getAllToolNames(): string[];
|
|
26
|
+
/**
|
|
27
|
+
* Creates a function to register all tools with the server.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createRegisterTools(clientFactory: GCSClientFactory, enabledGroups?: ToolGroup[]): (server: Server) => void;
|
|
30
|
+
//# sourceMappingURL=tools.d.ts.map
|
package/shared/tools.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { listBucketsTool } from './tools/list-buckets.js';
|
|
3
|
+
import { listObjectsTool } from './tools/list-objects.js';
|
|
4
|
+
import { getObjectTool } from './tools/get-object.js';
|
|
5
|
+
import { putObjectTool } from './tools/put-object.js';
|
|
6
|
+
import { deleteObjectTool } from './tools/delete-object.js';
|
|
7
|
+
import { createBucketTool } from './tools/create-bucket.js';
|
|
8
|
+
import { deleteBucketTool } from './tools/delete-bucket.js';
|
|
9
|
+
import { copyObjectTool } from './tools/copy-object.js';
|
|
10
|
+
import { headBucketTool } from './tools/head-bucket.js';
|
|
11
|
+
import { logWarning, logInfo } from './logging.js';
|
|
12
|
+
const ALL_TOOL_GROUPS = ['readonly', 'readwrite'];
|
|
13
|
+
/**
|
|
14
|
+
* Parse enabled tool groups from environment variable.
|
|
15
|
+
* @param enabledGroupsParam - Comma-separated list of groups (e.g., "readonly,readwrite")
|
|
16
|
+
* @returns Array of enabled tool groups
|
|
17
|
+
*/
|
|
18
|
+
export function parseEnabledToolGroups(enabledGroupsParam) {
|
|
19
|
+
if (!enabledGroupsParam) {
|
|
20
|
+
return ALL_TOOL_GROUPS; // All groups enabled by default
|
|
21
|
+
}
|
|
22
|
+
const requestedGroups = enabledGroupsParam.split(',').map((g) => g.trim().toLowerCase());
|
|
23
|
+
const validGroups = requestedGroups.filter((g) => ALL_TOOL_GROUPS.includes(g));
|
|
24
|
+
if (validGroups.length === 0) {
|
|
25
|
+
logWarning('parseEnabledToolGroups', `No valid tool groups found in "${enabledGroupsParam}". Valid groups: ${ALL_TOOL_GROUPS.join(', ')}. Using all groups.`);
|
|
26
|
+
return ALL_TOOL_GROUPS;
|
|
27
|
+
}
|
|
28
|
+
return validGroups;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Parse enabled/disabled tools from environment variables.
|
|
32
|
+
*/
|
|
33
|
+
export function parseToolFilters(enabledToolsParam, disabledToolsParam) {
|
|
34
|
+
const enabledTools = enabledToolsParam
|
|
35
|
+
? new Set(enabledToolsParam.split(',').map((t) => t.trim()))
|
|
36
|
+
: null;
|
|
37
|
+
const disabledTools = new Set(disabledToolsParam ? disabledToolsParam.split(',').map((t) => t.trim()) : []);
|
|
38
|
+
return { enabledTools, disabledTools };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* All available GCS tools with their group assignments.
|
|
42
|
+
*/
|
|
43
|
+
const ALL_TOOLS = [
|
|
44
|
+
// Read-only operations
|
|
45
|
+
{ factory: listBucketsTool, groups: ['readonly'], bucketLevelOnly: true },
|
|
46
|
+
{ factory: listObjectsTool, groups: ['readonly'], bucketParams: ['bucket'] },
|
|
47
|
+
{ factory: getObjectTool, groups: ['readonly'], bucketParams: ['bucket'] },
|
|
48
|
+
{ factory: headBucketTool, groups: ['readonly'], bucketLevelOnly: true },
|
|
49
|
+
// Write operations
|
|
50
|
+
{ factory: putObjectTool, groups: ['readwrite'], bucketParams: ['bucket'] },
|
|
51
|
+
{ factory: deleteObjectTool, groups: ['readwrite'], bucketParams: ['bucket'] },
|
|
52
|
+
{ factory: copyObjectTool, groups: ['readwrite'], bucketParams: ['sourceBucket', 'destBucket'] },
|
|
53
|
+
{ factory: createBucketTool, groups: ['readwrite'], bucketLevelOnly: true },
|
|
54
|
+
{ factory: deleteBucketTool, groups: ['readwrite'], bucketLevelOnly: true },
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* Get all tool names for documentation/help purposes.
|
|
58
|
+
*/
|
|
59
|
+
export function getAllToolNames() {
|
|
60
|
+
const mockServer = { setRequestHandler: () => { } };
|
|
61
|
+
const mockFactory = (() => { });
|
|
62
|
+
return ALL_TOOLS.map((def) => def.factory(mockServer, mockFactory).name);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wraps a tool to inject bucket parameter(s) when GCS_BUCKET is set.
|
|
66
|
+
*/
|
|
67
|
+
function wrapToolForBucketConstraint(tool, bucketParams, constrainedBucket) {
|
|
68
|
+
// Modify input schema to remove bucket params (they're injected automatically)
|
|
69
|
+
const newProperties = { ...tool.inputSchema.properties };
|
|
70
|
+
const newRequired = (tool.inputSchema.required || []).filter((r) => !bucketParams.includes(r));
|
|
71
|
+
for (const param of bucketParams) {
|
|
72
|
+
delete newProperties[param];
|
|
73
|
+
}
|
|
74
|
+
// Update description to indicate bucket constraint
|
|
75
|
+
const constraintNote = `\n\n**Note:** Operations are constrained to bucket "${constrainedBucket}".`;
|
|
76
|
+
return {
|
|
77
|
+
...tool,
|
|
78
|
+
description: tool.description + constraintNote,
|
|
79
|
+
inputSchema: {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: newProperties,
|
|
82
|
+
required: newRequired.length > 0 ? newRequired : undefined,
|
|
83
|
+
},
|
|
84
|
+
handler: async (args) => {
|
|
85
|
+
// Inject the constrained bucket into the args
|
|
86
|
+
const argsWithBucket = { ...args };
|
|
87
|
+
for (const param of bucketParams) {
|
|
88
|
+
argsWithBucket[param] = constrainedBucket;
|
|
89
|
+
}
|
|
90
|
+
return await tool.handler(argsWithBucket);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Creates a function to register all tools with the server.
|
|
96
|
+
*/
|
|
97
|
+
export function createRegisterTools(clientFactory, enabledGroups) {
|
|
98
|
+
const groups = enabledGroups || parseEnabledToolGroups(process.env.GCS_ENABLED_TOOLGROUPS);
|
|
99
|
+
const constrainedBucket = process.env.GCS_BUCKET;
|
|
100
|
+
// Parse individual tool filters
|
|
101
|
+
const { enabledTools, disabledTools } = parseToolFilters(process.env.GCS_ENABLED_TOOLS, process.env.GCS_DISABLED_TOOLS);
|
|
102
|
+
return (server) => {
|
|
103
|
+
// Filter tools by enabled groups first
|
|
104
|
+
let filteredToolDefs = ALL_TOOLS.filter((def) => def.groups.some((g) => groups.includes(g)));
|
|
105
|
+
// If GCS_BUCKET is set, filter out bucket-level-only tools
|
|
106
|
+
if (constrainedBucket) {
|
|
107
|
+
filteredToolDefs = filteredToolDefs.filter((def) => !def.bucketLevelOnly);
|
|
108
|
+
logInfo('config', `Bucket constraint active: ${constrainedBucket}`);
|
|
109
|
+
}
|
|
110
|
+
// Create tool instances
|
|
111
|
+
let tools = filteredToolDefs.map((def) => {
|
|
112
|
+
const tool = def.factory(server, clientFactory);
|
|
113
|
+
// If bucket is constrained and this tool has bucket params, wrap it
|
|
114
|
+
if (constrainedBucket && def.bucketParams && def.bucketParams.length > 0) {
|
|
115
|
+
return wrapToolForBucketConstraint(tool, def.bucketParams, constrainedBucket);
|
|
116
|
+
}
|
|
117
|
+
return tool;
|
|
118
|
+
});
|
|
119
|
+
// Apply individual tool filters
|
|
120
|
+
if (enabledTools) {
|
|
121
|
+
tools = tools.filter((tool) => enabledTools.has(tool.name));
|
|
122
|
+
}
|
|
123
|
+
tools = tools.filter((tool) => !disabledTools.has(tool.name));
|
|
124
|
+
// Log configuration for debugging
|
|
125
|
+
if (process.env.GCS_ENABLED_TOOLGROUPS) {
|
|
126
|
+
logWarning('config', `Tool groups enabled: ${groups.join(', ')}`);
|
|
127
|
+
}
|
|
128
|
+
if (enabledTools) {
|
|
129
|
+
logWarning('config', `Enabled tools filter: ${[...enabledTools].join(', ')}`);
|
|
130
|
+
}
|
|
131
|
+
if (disabledTools.size > 0) {
|
|
132
|
+
logWarning('config', `Disabled tools: ${[...disabledTools].join(', ')}`);
|
|
133
|
+
}
|
|
134
|
+
// List available tools
|
|
135
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
136
|
+
return {
|
|
137
|
+
tools: tools.map((tool) => ({
|
|
138
|
+
name: tool.name,
|
|
139
|
+
description: tool.description,
|
|
140
|
+
inputSchema: tool.inputSchema,
|
|
141
|
+
})),
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
// Handle tool calls
|
|
145
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
146
|
+
const { name, arguments: args } = request.params;
|
|
147
|
+
const tool = tools.find((t) => t.name === name);
|
|
148
|
+
if (!tool) {
|
|
149
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
150
|
+
}
|
|
151
|
+
return await tool.handler(args);
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.d.ts.map
|
package/shared/types.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// SHARED TYPE DEFINITIONS
|
|
4
|
+
// =============================================================================
|
|
5
|
+
// Common types used across the GCS MCP server.
|
|
6
|
+
// =============================================================================
|