oracle-cloud-mcp 1.0.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.
Files changed (3) hide show
  1. package/README.md +187 -0
  2. package/index.js +813 -0
  3. package/package.json +32 -0
package/README.md ADDED
@@ -0,0 +1,187 @@
1
+ # Oracle Cloud Infrastructure MCP Server
2
+
3
+ MCP server for Oracle Cloud Infrastructure (OCI) integration with Claude Code. Provides comprehensive access to OCI services including Compute, Storage, Networking, Database, and IAM.
4
+
5
+ ## Features
6
+
7
+ - **Compute** - List, manage, and control VM instances
8
+ - **Object Storage** - Manage buckets and objects
9
+ - **Block Storage** - List block and boot volumes
10
+ - **Networking** - VCNs, subnets, and network management
11
+ - **Autonomous Database** - ATP/ADW database operations
12
+ - **IAM** - Users, groups, policies, and compartments
13
+
14
+ ## Available Tools (21 total)
15
+
16
+ ### Compute (4 tools)
17
+ | Tool | Description |
18
+ |------|-------------|
19
+ | `oci_compute_list_instances` | List all compute instances in a compartment |
20
+ | `oci_compute_get_instance` | Get detailed info about a specific instance |
21
+ | `oci_compute_list_shapes` | List available shapes (incl. Always Free) |
22
+ | `oci_compute_instance_action` | Perform actions (START, STOP, RESET, etc.) |
23
+
24
+ ### Object Storage (5 tools)
25
+ | Tool | Description |
26
+ |------|-------------|
27
+ | `oci_os_get_namespace` | Get the Object Storage namespace |
28
+ | `oci_os_list_buckets` | List all buckets in compartment |
29
+ | `oci_os_create_bucket` | Create a new bucket |
30
+ | `oci_os_list_objects` | List objects in a bucket |
31
+ | `oci_os_delete_bucket` | Delete an empty bucket |
32
+
33
+ ### Block Storage (2 tools)
34
+ | Tool | Description |
35
+ |------|-------------|
36
+ | `oci_bv_list_volumes` | List block volumes |
37
+ | `oci_bv_list_boot_volumes` | List boot volumes |
38
+
39
+ ### Networking (3 tools)
40
+ | Tool | Description |
41
+ |------|-------------|
42
+ | `oci_vcn_list` | List Virtual Cloud Networks |
43
+ | `oci_subnet_list` | List subnets in a VCN |
44
+ | `oci_vcn_create` | Create a new VCN |
45
+
46
+ ### Autonomous Database (4 tools)
47
+ | Tool | Description |
48
+ |------|-------------|
49
+ | `oci_adb_list` | List Autonomous Databases |
50
+ | `oci_adb_get` | Get database details |
51
+ | `oci_adb_start` | Start a stopped database |
52
+ | `oci_adb_stop` | Stop a running database |
53
+
54
+ ### IAM (5 tools)
55
+ | Tool | Description |
56
+ |------|-------------|
57
+ | `oci_iam_list_users` | List IAM users |
58
+ | `oci_iam_list_groups` | List IAM groups |
59
+ | `oci_iam_list_policies` | List IAM policies |
60
+ | `oci_iam_list_compartments` | List compartments |
61
+ | `oci_iam_list_availability_domains` | List availability domains |
62
+
63
+ ## Setup
64
+
65
+ ### 1. Install Dependencies
66
+
67
+ ```bash
68
+ cd ~/mcp-servers/oracle-mcp
69
+ npm install
70
+ ```
71
+
72
+ ### 2. Configure OCI
73
+
74
+ Ensure you have OCI CLI configured with a valid config file:
75
+
76
+ ```bash
77
+ # ~/.oci/config should contain:
78
+ [DEFAULT]
79
+ user=ocid1.user.oc1..xxx
80
+ fingerprint=xx:xx:xx:xx:xx
81
+ tenancy=ocid1.tenancy.oc1..xxx
82
+ region=us-chicago-1
83
+ key_file=~/.oci/api_keys/oci_api_key.pem
84
+ ```
85
+
86
+ Or use session token authentication:
87
+ ```bash
88
+ oci session authenticate
89
+ ```
90
+
91
+ ### 3. Add to Claude Code
92
+
93
+ Add to `~/.claude.json`:
94
+
95
+ ```json
96
+ {
97
+ "mcpServers": {
98
+ "oracle": {
99
+ "type": "stdio",
100
+ "command": "node",
101
+ "args": ["/Users/matthewkarsten/mcp-servers/oracle-mcp/index.js"],
102
+ "env": {
103
+ "OCI_CONFIG_FILE": "/Users/matthewkarsten/.oci/config",
104
+ "OCI_PROFILE": "DEFAULT",
105
+ "OCI_REGION": "us-chicago-1"
106
+ }
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ ## Free Tier Resources
113
+
114
+ Oracle Cloud Free Tier includes:
115
+
116
+ | Resource | Free Allocation |
117
+ |----------|-----------------|
118
+ | Compute (Ampere A1) | 4 OCPUs, 24 GB RAM |
119
+ | Compute (AMD E2.1.Micro) | 2 instances |
120
+ | Object Storage | 20 GB Standard + 20 GB Archive |
121
+ | Block Storage | 200 GB total |
122
+ | Autonomous Database | 2 Always Free databases |
123
+ | Outbound Data | 10 TB/month |
124
+
125
+ ## Architecture
126
+
127
+ ```
128
+ Claude Code (Opus 4.5)
129
+
130
+ └──▶ Oracle MCP Server
131
+
132
+ └──▶ OCI SDK
133
+
134
+ ├── Compute Service
135
+ ├── Object Storage
136
+ ├── Block Storage
137
+ ├── Virtual Network
138
+ ├── Database Service
139
+ └── Identity Service
140
+ ```
141
+
142
+ ## Authentication
143
+
144
+ The server supports two authentication methods:
145
+
146
+ 1. **Session Token** (recommended for interactive use)
147
+ - Uses `security_token_file` from config
148
+ - Refreshable with `oci session refresh`
149
+
150
+ 2. **API Key** (for automation)
151
+ - Uses RSA key pair
152
+ - Requires fingerprint in OCI config
153
+
154
+ ## Usage Examples
155
+
156
+ ```
157
+ User: List my OCI compute instances
158
+
159
+ Claude: [Uses oci_compute_list_instances tool]
160
+ Result:
161
+ - web-server-1 (VM.Standard.A1.Flex) - RUNNING
162
+ - db-server (VM.Standard.E2.1.Micro) - STOPPED
163
+
164
+ User: Start the db-server instance
165
+
166
+ Claude: [Uses oci_compute_instance_action with action=START]
167
+ Result: Instance db-server is now starting...
168
+ ```
169
+
170
+ ## Files
171
+
172
+ - `index.js` - MCP server implementation
173
+ - `package.json` - Dependencies
174
+ - `README.md` - This file
175
+
176
+ ## Dependencies
177
+
178
+ - `@modelcontextprotocol/sdk` - MCP SDK
179
+ - `oci-sdk` - Official Oracle Cloud SDK
180
+
181
+ ## Author
182
+
183
+ Matthew Karsten
184
+
185
+ ## License
186
+
187
+ MIT
package/index.js ADDED
@@ -0,0 +1,813 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Oracle Cloud Infrastructure (OCI) MCP Server
5
+ *
6
+ * Provides Claude Code with access to Oracle Cloud services:
7
+ * - Compute (VM instances, shapes)
8
+ * - Object Storage (buckets, objects)
9
+ * - Block Storage (boot/block volumes)
10
+ * - Networking (VCNs, subnets, security lists)
11
+ * - Autonomous Database (ATP, ADW)
12
+ * - IAM (users, groups, policies)
13
+ */
14
+
15
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
16
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
17
+ import {
18
+ CallToolRequestSchema,
19
+ ListToolsRequestSchema,
20
+ } from "@modelcontextprotocol/sdk/types.js";
21
+ import * as oci from "oci-sdk";
22
+ import * as fs from "fs";
23
+ import * as path from "path";
24
+
25
+ // Configuration
26
+ const CONFIG_FILE = process.env.OCI_CONFIG_FILE || path.join(process.env.HOME, ".oci", "config");
27
+ const PROFILE = process.env.OCI_PROFILE || "DEFAULT";
28
+ const TENANCY_OCID = process.env.OCI_TENANCY_OCID;
29
+ const REGION = process.env.OCI_REGION || "us-chicago-1";
30
+
31
+ // Initialize OCI clients
32
+ let computeClient, objectStorageClient, blockStorageClient,
33
+ virtualNetworkClient, databaseClient, identityClient;
34
+
35
+ async function initializeClients() {
36
+ try {
37
+ // Try session token auth first, then fall back to API key
38
+ let provider;
39
+
40
+ const configFile = fs.readFileSync(CONFIG_FILE, "utf8");
41
+ if (configFile.includes("security_token_file")) {
42
+ // Session token authentication
43
+ provider = new oci.common.SessionAuthDetailProvider(CONFIG_FILE, PROFILE);
44
+ } else {
45
+ // API key authentication
46
+ provider = new oci.common.ConfigFileAuthenticationDetailsProvider(CONFIG_FILE, PROFILE);
47
+ }
48
+
49
+ computeClient = new oci.core.ComputeClient({ authenticationDetailsProvider: provider });
50
+ objectStorageClient = new oci.objectstorage.ObjectStorageClient({ authenticationDetailsProvider: provider });
51
+ blockStorageClient = new oci.core.BlockstorageClient({ authenticationDetailsProvider: provider });
52
+ virtualNetworkClient = new oci.core.VirtualNetworkClient({ authenticationDetailsProvider: provider });
53
+ databaseClient = new oci.database.DatabaseClient({ authenticationDetailsProvider: provider });
54
+ identityClient = new oci.identity.IdentityClient({ authenticationDetailsProvider: provider });
55
+
56
+ console.error("OCI clients initialized successfully");
57
+ return true;
58
+ } catch (error) {
59
+ console.error("Failed to initialize OCI clients:", error.message);
60
+ return false;
61
+ }
62
+ }
63
+
64
+ // Helper to get compartment ID (default to tenancy)
65
+ function getCompartmentId(params) {
66
+ return params.compartment_id || TENANCY_OCID || process.env.OCI_TENANCY_OCID;
67
+ }
68
+
69
+ // Tool handlers
70
+ const toolHandlers = {
71
+ // ==================== COMPUTE ====================
72
+
73
+ async oci_compute_list_instances(params) {
74
+ const response = await computeClient.listInstances({
75
+ compartmentId: getCompartmentId(params),
76
+ limit: params.limit || 50,
77
+ });
78
+
79
+ return response.items.map(instance => ({
80
+ id: instance.id,
81
+ displayName: instance.displayName,
82
+ shape: instance.shape,
83
+ lifecycleState: instance.lifecycleState,
84
+ availabilityDomain: instance.availabilityDomain,
85
+ region: instance.region,
86
+ timeCreated: instance.timeCreated,
87
+ }));
88
+ },
89
+
90
+ async oci_compute_get_instance(params) {
91
+ const response = await computeClient.getInstance({
92
+ instanceId: params.instance_id,
93
+ });
94
+
95
+ return {
96
+ id: response.instance.id,
97
+ displayName: response.instance.displayName,
98
+ shape: response.instance.shape,
99
+ lifecycleState: response.instance.lifecycleState,
100
+ availabilityDomain: response.instance.availabilityDomain,
101
+ faultDomain: response.instance.faultDomain,
102
+ region: response.instance.region,
103
+ imageId: response.instance.imageId,
104
+ timeCreated: response.instance.timeCreated,
105
+ metadata: response.instance.metadata,
106
+ shapeConfig: response.instance.shapeConfig,
107
+ };
108
+ },
109
+
110
+ async oci_compute_list_shapes(params) {
111
+ const response = await computeClient.listShapes({
112
+ compartmentId: getCompartmentId(params),
113
+ limit: params.limit || 100,
114
+ });
115
+
116
+ return response.items.map(shape => ({
117
+ shape: shape.shape,
118
+ processorDescription: shape.processorDescription,
119
+ ocpus: shape.ocpus,
120
+ memoryInGBs: shape.memoryInGBs,
121
+ networkingBandwidthInGbps: shape.networkingBandwidthInGbps,
122
+ maxVnicAttachments: shape.maxVnicAttachments,
123
+ gpus: shape.gpus,
124
+ isFlexible: shape.isFlexible,
125
+ }));
126
+ },
127
+
128
+ async oci_compute_instance_action(params) {
129
+ const response = await computeClient.instanceAction({
130
+ instanceId: params.instance_id,
131
+ action: params.action, // START, STOP, RESET, SOFTSTOP, SOFTRESET
132
+ });
133
+
134
+ return {
135
+ id: response.instance.id,
136
+ displayName: response.instance.displayName,
137
+ lifecycleState: response.instance.lifecycleState,
138
+ action: params.action,
139
+ };
140
+ },
141
+
142
+ // ==================== OBJECT STORAGE ====================
143
+
144
+ async oci_os_get_namespace(params) {
145
+ const response = await objectStorageClient.getNamespace({
146
+ compartmentId: getCompartmentId(params),
147
+ });
148
+ return { namespace: response.value };
149
+ },
150
+
151
+ async oci_os_list_buckets(params) {
152
+ const nsResponse = await objectStorageClient.getNamespace({
153
+ compartmentId: getCompartmentId(params),
154
+ });
155
+
156
+ const response = await objectStorageClient.listBuckets({
157
+ namespaceName: nsResponse.value,
158
+ compartmentId: getCompartmentId(params),
159
+ limit: params.limit || 100,
160
+ });
161
+
162
+ return response.items.map(bucket => ({
163
+ name: bucket.name,
164
+ namespace: bucket.namespace,
165
+ compartmentId: bucket.compartmentId,
166
+ createdBy: bucket.createdBy,
167
+ timeCreated: bucket.timeCreated,
168
+ etag: bucket.etag,
169
+ }));
170
+ },
171
+
172
+ async oci_os_create_bucket(params) {
173
+ const nsResponse = await objectStorageClient.getNamespace({
174
+ compartmentId: getCompartmentId(params),
175
+ });
176
+
177
+ const response = await objectStorageClient.createBucket({
178
+ namespaceName: nsResponse.value,
179
+ createBucketDetails: {
180
+ name: params.bucket_name,
181
+ compartmentId: getCompartmentId(params),
182
+ publicAccessType: params.public_access || "NoPublicAccess",
183
+ storageTier: params.storage_tier || "Standard",
184
+ },
185
+ });
186
+
187
+ return {
188
+ name: response.bucket.name,
189
+ namespace: response.bucket.namespace,
190
+ compartmentId: response.bucket.compartmentId,
191
+ timeCreated: response.bucket.timeCreated,
192
+ };
193
+ },
194
+
195
+ async oci_os_list_objects(params) {
196
+ const nsResponse = await objectStorageClient.getNamespace({
197
+ compartmentId: getCompartmentId(params),
198
+ });
199
+
200
+ const response = await objectStorageClient.listObjects({
201
+ namespaceName: nsResponse.value,
202
+ bucketName: params.bucket_name,
203
+ prefix: params.prefix,
204
+ limit: params.limit || 100,
205
+ });
206
+
207
+ return response.listObjects.objects.map(obj => ({
208
+ name: obj.name,
209
+ size: obj.size,
210
+ md5: obj.md5,
211
+ timeCreated: obj.timeCreated,
212
+ timeModified: obj.timeModified,
213
+ }));
214
+ },
215
+
216
+ async oci_os_delete_bucket(params) {
217
+ const nsResponse = await objectStorageClient.getNamespace({
218
+ compartmentId: getCompartmentId(params),
219
+ });
220
+
221
+ await objectStorageClient.deleteBucket({
222
+ namespaceName: nsResponse.value,
223
+ bucketName: params.bucket_name,
224
+ });
225
+
226
+ return { deleted: true, bucket: params.bucket_name };
227
+ },
228
+
229
+ // ==================== BLOCK STORAGE ====================
230
+
231
+ async oci_bv_list_volumes(params) {
232
+ const response = await blockStorageClient.listVolumes({
233
+ compartmentId: getCompartmentId(params),
234
+ limit: params.limit || 50,
235
+ });
236
+
237
+ return response.items.map(vol => ({
238
+ id: vol.id,
239
+ displayName: vol.displayName,
240
+ sizeInGBs: vol.sizeInGBs,
241
+ lifecycleState: vol.lifecycleState,
242
+ availabilityDomain: vol.availabilityDomain,
243
+ vpusPerGB: vol.vpusPerGB,
244
+ timeCreated: vol.timeCreated,
245
+ }));
246
+ },
247
+
248
+ async oci_bv_list_boot_volumes(params) {
249
+ const response = await blockStorageClient.listBootVolumes({
250
+ compartmentId: getCompartmentId(params),
251
+ availabilityDomain: params.availability_domain,
252
+ limit: params.limit || 50,
253
+ });
254
+
255
+ return response.items.map(vol => ({
256
+ id: vol.id,
257
+ displayName: vol.displayName,
258
+ sizeInGBs: vol.sizeInGBs,
259
+ lifecycleState: vol.lifecycleState,
260
+ availabilityDomain: vol.availabilityDomain,
261
+ imageId: vol.imageId,
262
+ timeCreated: vol.timeCreated,
263
+ }));
264
+ },
265
+
266
+ // ==================== NETWORKING ====================
267
+
268
+ async oci_vcn_list(params) {
269
+ const response = await virtualNetworkClient.listVcns({
270
+ compartmentId: getCompartmentId(params),
271
+ limit: params.limit || 50,
272
+ });
273
+
274
+ return response.items.map(vcn => ({
275
+ id: vcn.id,
276
+ displayName: vcn.displayName,
277
+ cidrBlock: vcn.cidrBlock,
278
+ cidrBlocks: vcn.cidrBlocks,
279
+ lifecycleState: vcn.lifecycleState,
280
+ dnsLabel: vcn.dnsLabel,
281
+ defaultRouteTableId: vcn.defaultRouteTableId,
282
+ defaultSecurityListId: vcn.defaultSecurityListId,
283
+ timeCreated: vcn.timeCreated,
284
+ }));
285
+ },
286
+
287
+ async oci_subnet_list(params) {
288
+ const response = await virtualNetworkClient.listSubnets({
289
+ compartmentId: getCompartmentId(params),
290
+ vcnId: params.vcn_id,
291
+ limit: params.limit || 50,
292
+ });
293
+
294
+ return response.items.map(subnet => ({
295
+ id: subnet.id,
296
+ displayName: subnet.displayName,
297
+ cidrBlock: subnet.cidrBlock,
298
+ availabilityDomain: subnet.availabilityDomain,
299
+ lifecycleState: subnet.lifecycleState,
300
+ virtualRouterIp: subnet.virtualRouterIp,
301
+ securityListIds: subnet.securityListIds,
302
+ timeCreated: subnet.timeCreated,
303
+ }));
304
+ },
305
+
306
+ async oci_vcn_create(params) {
307
+ const response = await virtualNetworkClient.createVcn({
308
+ createVcnDetails: {
309
+ compartmentId: getCompartmentId(params),
310
+ displayName: params.display_name,
311
+ cidrBlocks: params.cidr_blocks || ["10.0.0.0/16"],
312
+ dnsLabel: params.dns_label,
313
+ },
314
+ });
315
+
316
+ return {
317
+ id: response.vcn.id,
318
+ displayName: response.vcn.displayName,
319
+ cidrBlocks: response.vcn.cidrBlocks,
320
+ lifecycleState: response.vcn.lifecycleState,
321
+ timeCreated: response.vcn.timeCreated,
322
+ };
323
+ },
324
+
325
+ // ==================== AUTONOMOUS DATABASE ====================
326
+
327
+ async oci_adb_list(params) {
328
+ const response = await databaseClient.listAutonomousDatabases({
329
+ compartmentId: getCompartmentId(params),
330
+ limit: params.limit || 50,
331
+ });
332
+
333
+ return response.items.map(db => ({
334
+ id: db.id,
335
+ displayName: db.displayName,
336
+ dbName: db.dbName,
337
+ dbWorkload: db.dbWorkload,
338
+ lifecycleState: db.lifecycleState,
339
+ cpuCoreCount: db.cpuCoreCount,
340
+ dataStorageSizeInTBs: db.dataStorageSizeInTBs,
341
+ isFreeTier: db.isFreeTier,
342
+ connectionStrings: db.connectionStrings?.profiles?.map(p => p.displayName),
343
+ timeCreated: db.timeCreated,
344
+ }));
345
+ },
346
+
347
+ async oci_adb_get(params) {
348
+ const response = await databaseClient.getAutonomousDatabase({
349
+ autonomousDatabaseId: params.database_id,
350
+ });
351
+
352
+ return {
353
+ id: response.autonomousDatabase.id,
354
+ displayName: response.autonomousDatabase.displayName,
355
+ dbName: response.autonomousDatabase.dbName,
356
+ dbWorkload: response.autonomousDatabase.dbWorkload,
357
+ lifecycleState: response.autonomousDatabase.lifecycleState,
358
+ cpuCoreCount: response.autonomousDatabase.cpuCoreCount,
359
+ dataStorageSizeInTBs: response.autonomousDatabase.dataStorageSizeInTBs,
360
+ isFreeTier: response.autonomousDatabase.isFreeTier,
361
+ connectionStrings: response.autonomousDatabase.connectionStrings,
362
+ serviceConsoleUrl: response.autonomousDatabase.serviceConsoleUrl,
363
+ timeCreated: response.autonomousDatabase.timeCreated,
364
+ };
365
+ },
366
+
367
+ async oci_adb_start(params) {
368
+ const response = await databaseClient.startAutonomousDatabase({
369
+ autonomousDatabaseId: params.database_id,
370
+ });
371
+
372
+ return {
373
+ id: response.autonomousDatabase.id,
374
+ displayName: response.autonomousDatabase.displayName,
375
+ lifecycleState: response.autonomousDatabase.lifecycleState,
376
+ action: "START",
377
+ };
378
+ },
379
+
380
+ async oci_adb_stop(params) {
381
+ const response = await databaseClient.stopAutonomousDatabase({
382
+ autonomousDatabaseId: params.database_id,
383
+ });
384
+
385
+ return {
386
+ id: response.autonomousDatabase.id,
387
+ displayName: response.autonomousDatabase.displayName,
388
+ lifecycleState: response.autonomousDatabase.lifecycleState,
389
+ action: "STOP",
390
+ };
391
+ },
392
+
393
+ // ==================== IAM ====================
394
+
395
+ async oci_iam_list_users(params) {
396
+ const response = await identityClient.listUsers({
397
+ compartmentId: getCompartmentId(params),
398
+ limit: params.limit || 100,
399
+ });
400
+
401
+ return response.items.map(user => ({
402
+ id: user.id,
403
+ name: user.name,
404
+ email: user.email,
405
+ description: user.description,
406
+ lifecycleState: user.lifecycleState,
407
+ isMfaActivated: user.isMfaActivated,
408
+ timeCreated: user.timeCreated,
409
+ }));
410
+ },
411
+
412
+ async oci_iam_list_groups(params) {
413
+ const response = await identityClient.listGroups({
414
+ compartmentId: getCompartmentId(params),
415
+ limit: params.limit || 100,
416
+ });
417
+
418
+ return response.items.map(group => ({
419
+ id: group.id,
420
+ name: group.name,
421
+ description: group.description,
422
+ lifecycleState: group.lifecycleState,
423
+ timeCreated: group.timeCreated,
424
+ }));
425
+ },
426
+
427
+ async oci_iam_list_policies(params) {
428
+ const response = await identityClient.listPolicies({
429
+ compartmentId: getCompartmentId(params),
430
+ limit: params.limit || 100,
431
+ });
432
+
433
+ return response.items.map(policy => ({
434
+ id: policy.id,
435
+ name: policy.name,
436
+ description: policy.description,
437
+ statements: policy.statements,
438
+ lifecycleState: policy.lifecycleState,
439
+ timeCreated: policy.timeCreated,
440
+ }));
441
+ },
442
+
443
+ async oci_iam_list_compartments(params) {
444
+ const response = await identityClient.listCompartments({
445
+ compartmentId: getCompartmentId(params),
446
+ limit: params.limit || 100,
447
+ accessLevel: "ANY",
448
+ compartmentIdInSubtree: true,
449
+ });
450
+
451
+ return response.items.map(compartment => ({
452
+ id: compartment.id,
453
+ name: compartment.name,
454
+ description: compartment.description,
455
+ lifecycleState: compartment.lifecycleState,
456
+ timeCreated: compartment.timeCreated,
457
+ }));
458
+ },
459
+
460
+ async oci_iam_list_availability_domains(params) {
461
+ const response = await identityClient.listAvailabilityDomains({
462
+ compartmentId: getCompartmentId(params),
463
+ });
464
+
465
+ return response.items.map(ad => ({
466
+ id: ad.id,
467
+ name: ad.name,
468
+ }));
469
+ },
470
+ };
471
+
472
+ // Tool definitions
473
+ const tools = [
474
+ // Compute
475
+ {
476
+ name: "oci_compute_list_instances",
477
+ description: "List all compute instances in a compartment. Shows VM details including shape, state, and availability domain.",
478
+ inputSchema: {
479
+ type: "object",
480
+ properties: {
481
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
482
+ limit: { type: "number", description: "Maximum number of instances to return", default: 50 },
483
+ },
484
+ },
485
+ },
486
+ {
487
+ name: "oci_compute_get_instance",
488
+ description: "Get detailed information about a specific compute instance",
489
+ inputSchema: {
490
+ type: "object",
491
+ properties: {
492
+ instance_id: { type: "string", description: "Instance OCID" },
493
+ },
494
+ required: ["instance_id"],
495
+ },
496
+ },
497
+ {
498
+ name: "oci_compute_list_shapes",
499
+ description: "List available compute shapes including Always Free shapes (VM.Standard.A1.Flex, VM.Standard.E2.1.Micro)",
500
+ inputSchema: {
501
+ type: "object",
502
+ properties: {
503
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
504
+ limit: { type: "number", description: "Maximum shapes to return", default: 100 },
505
+ },
506
+ },
507
+ },
508
+ {
509
+ name: "oci_compute_instance_action",
510
+ description: "Perform action on a compute instance (START, STOP, RESET, SOFTSTOP, SOFTRESET)",
511
+ inputSchema: {
512
+ type: "object",
513
+ properties: {
514
+ instance_id: { type: "string", description: "Instance OCID" },
515
+ action: { type: "string", enum: ["START", "STOP", "RESET", "SOFTSTOP", "SOFTRESET"], description: "Action to perform" },
516
+ },
517
+ required: ["instance_id", "action"],
518
+ },
519
+ },
520
+
521
+ // Object Storage
522
+ {
523
+ name: "oci_os_get_namespace",
524
+ description: "Get the Object Storage namespace for the tenancy",
525
+ inputSchema: {
526
+ type: "object",
527
+ properties: {
528
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
529
+ },
530
+ },
531
+ },
532
+ {
533
+ name: "oci_os_list_buckets",
534
+ description: "List all Object Storage buckets in a compartment (Free Tier: 20GB standard, 20GB archive)",
535
+ inputSchema: {
536
+ type: "object",
537
+ properties: {
538
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
539
+ limit: { type: "number", description: "Maximum buckets to return", default: 100 },
540
+ },
541
+ },
542
+ },
543
+ {
544
+ name: "oci_os_create_bucket",
545
+ description: "Create a new Object Storage bucket",
546
+ inputSchema: {
547
+ type: "object",
548
+ properties: {
549
+ bucket_name: { type: "string", description: "Name for the new bucket" },
550
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
551
+ public_access: { type: "string", enum: ["NoPublicAccess", "ObjectRead", "ObjectReadWithoutList"], default: "NoPublicAccess" },
552
+ storage_tier: { type: "string", enum: ["Standard", "Archive"], default: "Standard" },
553
+ },
554
+ required: ["bucket_name"],
555
+ },
556
+ },
557
+ {
558
+ name: "oci_os_list_objects",
559
+ description: "List objects in a bucket with optional prefix filter",
560
+ inputSchema: {
561
+ type: "object",
562
+ properties: {
563
+ bucket_name: { type: "string", description: "Bucket name" },
564
+ prefix: { type: "string", description: "Filter objects by prefix" },
565
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
566
+ limit: { type: "number", description: "Maximum objects to return", default: 100 },
567
+ },
568
+ required: ["bucket_name"],
569
+ },
570
+ },
571
+ {
572
+ name: "oci_os_delete_bucket",
573
+ description: "Delete an empty Object Storage bucket",
574
+ inputSchema: {
575
+ type: "object",
576
+ properties: {
577
+ bucket_name: { type: "string", description: "Bucket name to delete" },
578
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
579
+ },
580
+ required: ["bucket_name"],
581
+ },
582
+ },
583
+
584
+ // Block Storage
585
+ {
586
+ name: "oci_bv_list_volumes",
587
+ description: "List block volumes in a compartment (Free Tier: 200GB total)",
588
+ inputSchema: {
589
+ type: "object",
590
+ properties: {
591
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
592
+ limit: { type: "number", description: "Maximum volumes to return", default: 50 },
593
+ },
594
+ },
595
+ },
596
+ {
597
+ name: "oci_bv_list_boot_volumes",
598
+ description: "List boot volumes in an availability domain",
599
+ inputSchema: {
600
+ type: "object",
601
+ properties: {
602
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
603
+ availability_domain: { type: "string", description: "Availability domain name" },
604
+ limit: { type: "number", description: "Maximum volumes to return", default: 50 },
605
+ },
606
+ },
607
+ },
608
+
609
+ // Networking
610
+ {
611
+ name: "oci_vcn_list",
612
+ description: "List Virtual Cloud Networks (VCNs) in a compartment",
613
+ inputSchema: {
614
+ type: "object",
615
+ properties: {
616
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
617
+ limit: { type: "number", description: "Maximum VCNs to return", default: 50 },
618
+ },
619
+ },
620
+ },
621
+ {
622
+ name: "oci_subnet_list",
623
+ description: "List subnets in a VCN",
624
+ inputSchema: {
625
+ type: "object",
626
+ properties: {
627
+ vcn_id: { type: "string", description: "VCN OCID" },
628
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
629
+ limit: { type: "number", description: "Maximum subnets to return", default: 50 },
630
+ },
631
+ required: ["vcn_id"],
632
+ },
633
+ },
634
+ {
635
+ name: "oci_vcn_create",
636
+ description: "Create a new Virtual Cloud Network",
637
+ inputSchema: {
638
+ type: "object",
639
+ properties: {
640
+ display_name: { type: "string", description: "Display name for the VCN" },
641
+ cidr_blocks: { type: "array", items: { type: "string" }, description: "CIDR blocks (e.g., ['10.0.0.0/16'])" },
642
+ dns_label: { type: "string", description: "DNS label for the VCN" },
643
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
644
+ },
645
+ required: ["display_name"],
646
+ },
647
+ },
648
+
649
+ // Autonomous Database
650
+ {
651
+ name: "oci_adb_list",
652
+ description: "List Autonomous Databases (ATP/ADW). Free Tier includes 2 Always Free ATP or ADW databases.",
653
+ inputSchema: {
654
+ type: "object",
655
+ properties: {
656
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
657
+ limit: { type: "number", description: "Maximum databases to return", default: 50 },
658
+ },
659
+ },
660
+ },
661
+ {
662
+ name: "oci_adb_get",
663
+ description: "Get detailed information about an Autonomous Database",
664
+ inputSchema: {
665
+ type: "object",
666
+ properties: {
667
+ database_id: { type: "string", description: "Autonomous Database OCID" },
668
+ },
669
+ required: ["database_id"],
670
+ },
671
+ },
672
+ {
673
+ name: "oci_adb_start",
674
+ description: "Start a stopped Autonomous Database",
675
+ inputSchema: {
676
+ type: "object",
677
+ properties: {
678
+ database_id: { type: "string", description: "Autonomous Database OCID" },
679
+ },
680
+ required: ["database_id"],
681
+ },
682
+ },
683
+ {
684
+ name: "oci_adb_stop",
685
+ description: "Stop a running Autonomous Database",
686
+ inputSchema: {
687
+ type: "object",
688
+ properties: {
689
+ database_id: { type: "string", description: "Autonomous Database OCID" },
690
+ },
691
+ required: ["database_id"],
692
+ },
693
+ },
694
+
695
+ // IAM
696
+ {
697
+ name: "oci_iam_list_users",
698
+ description: "List IAM users in the tenancy",
699
+ inputSchema: {
700
+ type: "object",
701
+ properties: {
702
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
703
+ limit: { type: "number", description: "Maximum users to return", default: 100 },
704
+ },
705
+ },
706
+ },
707
+ {
708
+ name: "oci_iam_list_groups",
709
+ description: "List IAM groups in the tenancy",
710
+ inputSchema: {
711
+ type: "object",
712
+ properties: {
713
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
714
+ limit: { type: "number", description: "Maximum groups to return", default: 100 },
715
+ },
716
+ },
717
+ },
718
+ {
719
+ name: "oci_iam_list_policies",
720
+ description: "List IAM policies in a compartment",
721
+ inputSchema: {
722
+ type: "object",
723
+ properties: {
724
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
725
+ limit: { type: "number", description: "Maximum policies to return", default: 100 },
726
+ },
727
+ },
728
+ },
729
+ {
730
+ name: "oci_iam_list_compartments",
731
+ description: "List compartments in the tenancy hierarchy",
732
+ inputSchema: {
733
+ type: "object",
734
+ properties: {
735
+ compartment_id: { type: "string", description: "Parent compartment OCID (defaults to tenancy)" },
736
+ limit: { type: "number", description: "Maximum compartments to return", default: 100 },
737
+ },
738
+ },
739
+ },
740
+ {
741
+ name: "oci_iam_list_availability_domains",
742
+ description: "List availability domains in the region",
743
+ inputSchema: {
744
+ type: "object",
745
+ properties: {
746
+ compartment_id: { type: "string", description: "Compartment OCID (defaults to tenancy)" },
747
+ },
748
+ },
749
+ },
750
+ ];
751
+
752
+ // Create and start the server
753
+ const server = new Server(
754
+ {
755
+ name: "oracle-cloud-mcp",
756
+ version: "1.0.0",
757
+ },
758
+ {
759
+ capabilities: {
760
+ tools: {},
761
+ },
762
+ }
763
+ );
764
+
765
+ // Handle list tools request
766
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
767
+ return { tools };
768
+ });
769
+
770
+ // Handle call tool request
771
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
772
+ const { name, arguments: params } = request.params;
773
+
774
+ if (!toolHandlers[name]) {
775
+ throw new Error(`Unknown tool: ${name}`);
776
+ }
777
+
778
+ try {
779
+ const result = await toolHandlers[name](params || {});
780
+ return {
781
+ content: [
782
+ {
783
+ type: "text",
784
+ text: JSON.stringify(result, null, 2),
785
+ },
786
+ ],
787
+ };
788
+ } catch (error) {
789
+ return {
790
+ content: [
791
+ {
792
+ type: "text",
793
+ text: `Error: ${error.message}`,
794
+ },
795
+ ],
796
+ isError: true,
797
+ };
798
+ }
799
+ });
800
+
801
+ // Start the server
802
+ async function main() {
803
+ await initializeClients();
804
+
805
+ const transport = new StdioServerTransport();
806
+ await server.connect(transport);
807
+ console.error("Oracle Cloud MCP server running");
808
+ }
809
+
810
+ main().catch((error) => {
811
+ console.error("Server error:", error);
812
+ process.exit(1);
813
+ });
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "oracle-cloud-mcp",
3
+ "mcpName": "io.github.ExpertVagabond/oracle-cloud",
4
+ "version": "1.0.1",
5
+ "description": "Oracle Cloud Infrastructure MCP Server for Claude Code",
6
+ "main": "index.js",
7
+ "type": "module",
8
+ "bin": {
9
+ "oracle-mcp-server": "index.js"
10
+ },
11
+ "scripts": {
12
+ "start": "node index.js",
13
+ "test": "echo \"Error: no test specified\" && exit 1"
14
+ },
15
+ "keywords": [
16
+ "oracle",
17
+ "oci",
18
+ "cloud",
19
+ "mcp"
20
+ ],
21
+ "author": "Matthew Karsten",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/ExpertVagabond/oracle-mcp.git"
26
+ },
27
+ "homepage": "https://github.com/ExpertVagabond/oracle-mcp#readme",
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.24.3",
30
+ "oci-sdk": "^2.122.1"
31
+ }
32
+ }