@purplesquirrel/oracle-mcp-server 1.0.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/.github/dependabot.yml +21 -0
- package/.github/workflows/ci.yml +36 -0
- package/LICENSE +21 -0
- package/README.md +192 -0
- package/index.js +813 -0
- package/package.json +18 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "npm"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
open-pull-requests-limit: 10
|
|
8
|
+
labels:
|
|
9
|
+
- "dependencies"
|
|
10
|
+
commit-message:
|
|
11
|
+
prefix: "chore(deps)"
|
|
12
|
+
|
|
13
|
+
- package-ecosystem: "github-actions"
|
|
14
|
+
directory: "/"
|
|
15
|
+
schedule:
|
|
16
|
+
interval: "weekly"
|
|
17
|
+
labels:
|
|
18
|
+
- "dependencies"
|
|
19
|
+
- "github-actions"
|
|
20
|
+
commit-message:
|
|
21
|
+
prefix: "chore(ci)"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
node-version: [18.x, 20.x]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
|
+
uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: ${{ matrix.node-version }}
|
|
24
|
+
cache: 'npm'
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: npm ci
|
|
28
|
+
|
|
29
|
+
- name: Run linter
|
|
30
|
+
run: npm run lint --if-present
|
|
31
|
+
|
|
32
|
+
- name: Run tests
|
|
33
|
+
run: npm test --if-present
|
|
34
|
+
|
|
35
|
+
- name: Build
|
|
36
|
+
run: npm run build --if-present
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Purple Squirrel Media
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
[](https://opensource.org/licenses/MIT)
|
|
2
|
+
[](https://modelcontextprotocol.io)
|
|
3
|
+
[](https://cloud.oracle.com)
|
|
4
|
+
[](https://github.com/PurpleSquirrelMedia/oracle-mcp-server/actions/workflows/ci.yml)
|
|
5
|
+
|
|
6
|
+
# Oracle Cloud Infrastructure MCP Server
|
|
7
|
+
|
|
8
|
+
MCP server for Oracle Cloud Infrastructure (OCI) integration with Claude Code. Provides comprehensive access to OCI services including Compute, Storage, Networking, Database, and IAM.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Compute** - List, manage, and control VM instances
|
|
13
|
+
- **Object Storage** - Manage buckets and objects
|
|
14
|
+
- **Block Storage** - List block and boot volumes
|
|
15
|
+
- **Networking** - VCNs, subnets, and network management
|
|
16
|
+
- **Autonomous Database** - ATP/ADW database operations
|
|
17
|
+
- **IAM** - Users, groups, policies, and compartments
|
|
18
|
+
|
|
19
|
+
## Available Tools (21 total)
|
|
20
|
+
|
|
21
|
+
### Compute (4 tools)
|
|
22
|
+
| Tool | Description |
|
|
23
|
+
|------|-------------|
|
|
24
|
+
| `oci_compute_list_instances` | List all compute instances in a compartment |
|
|
25
|
+
| `oci_compute_get_instance` | Get detailed info about a specific instance |
|
|
26
|
+
| `oci_compute_list_shapes` | List available shapes (incl. Always Free) |
|
|
27
|
+
| `oci_compute_instance_action` | Perform actions (START, STOP, RESET, etc.) |
|
|
28
|
+
|
|
29
|
+
### Object Storage (5 tools)
|
|
30
|
+
| Tool | Description |
|
|
31
|
+
|------|-------------|
|
|
32
|
+
| `oci_os_get_namespace` | Get the Object Storage namespace |
|
|
33
|
+
| `oci_os_list_buckets` | List all buckets in compartment |
|
|
34
|
+
| `oci_os_create_bucket` | Create a new bucket |
|
|
35
|
+
| `oci_os_list_objects` | List objects in a bucket |
|
|
36
|
+
| `oci_os_delete_bucket` | Delete an empty bucket |
|
|
37
|
+
|
|
38
|
+
### Block Storage (2 tools)
|
|
39
|
+
| Tool | Description |
|
|
40
|
+
|------|-------------|
|
|
41
|
+
| `oci_bv_list_volumes` | List block volumes |
|
|
42
|
+
| `oci_bv_list_boot_volumes` | List boot volumes |
|
|
43
|
+
|
|
44
|
+
### Networking (3 tools)
|
|
45
|
+
| Tool | Description |
|
|
46
|
+
|------|-------------|
|
|
47
|
+
| `oci_vcn_list` | List Virtual Cloud Networks |
|
|
48
|
+
| `oci_subnet_list` | List subnets in a VCN |
|
|
49
|
+
| `oci_vcn_create` | Create a new VCN |
|
|
50
|
+
|
|
51
|
+
### Autonomous Database (4 tools)
|
|
52
|
+
| Tool | Description |
|
|
53
|
+
|------|-------------|
|
|
54
|
+
| `oci_adb_list` | List Autonomous Databases |
|
|
55
|
+
| `oci_adb_get` | Get database details |
|
|
56
|
+
| `oci_adb_start` | Start a stopped database |
|
|
57
|
+
| `oci_adb_stop` | Stop a running database |
|
|
58
|
+
|
|
59
|
+
### IAM (5 tools)
|
|
60
|
+
| Tool | Description |
|
|
61
|
+
|------|-------------|
|
|
62
|
+
| `oci_iam_list_users` | List IAM users |
|
|
63
|
+
| `oci_iam_list_groups` | List IAM groups |
|
|
64
|
+
| `oci_iam_list_policies` | List IAM policies |
|
|
65
|
+
| `oci_iam_list_compartments` | List compartments |
|
|
66
|
+
| `oci_iam_list_availability_domains` | List availability domains |
|
|
67
|
+
|
|
68
|
+
## Setup
|
|
69
|
+
|
|
70
|
+
### 1. Install Dependencies
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
cd ~/mcp-servers/oracle-mcp
|
|
74
|
+
npm install
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 2. Configure OCI
|
|
78
|
+
|
|
79
|
+
Ensure you have OCI CLI configured with a valid config file:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# ~/.oci/config should contain:
|
|
83
|
+
[DEFAULT]
|
|
84
|
+
user=ocid1.user.oc1..xxx
|
|
85
|
+
fingerprint=xx:xx:xx:xx:xx
|
|
86
|
+
tenancy=ocid1.tenancy.oc1..xxx
|
|
87
|
+
region=us-chicago-1
|
|
88
|
+
key_file=~/.oci/api_keys/oci_api_key.pem
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or use session token authentication:
|
|
92
|
+
```bash
|
|
93
|
+
oci session authenticate
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Add to Claude Code
|
|
97
|
+
|
|
98
|
+
Add to `~/.claude.json`:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"mcpServers": {
|
|
103
|
+
"oracle": {
|
|
104
|
+
"type": "stdio",
|
|
105
|
+
"command": "node",
|
|
106
|
+
"args": ["/Users/matthewkarsten/mcp-servers/oracle-mcp/index.js"],
|
|
107
|
+
"env": {
|
|
108
|
+
"OCI_CONFIG_FILE": "/Users/matthewkarsten/.oci/config",
|
|
109
|
+
"OCI_PROFILE": "DEFAULT",
|
|
110
|
+
"OCI_REGION": "us-chicago-1"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Free Tier Resources
|
|
118
|
+
|
|
119
|
+
Oracle Cloud Free Tier includes:
|
|
120
|
+
|
|
121
|
+
| Resource | Free Allocation |
|
|
122
|
+
|----------|-----------------|
|
|
123
|
+
| Compute (Ampere A1) | 4 OCPUs, 24 GB RAM |
|
|
124
|
+
| Compute (AMD E2.1.Micro) | 2 instances |
|
|
125
|
+
| Object Storage | 20 GB Standard + 20 GB Archive |
|
|
126
|
+
| Block Storage | 200 GB total |
|
|
127
|
+
| Autonomous Database | 2 Always Free databases |
|
|
128
|
+
| Outbound Data | 10 TB/month |
|
|
129
|
+
|
|
130
|
+
## Architecture
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
Claude Code (Opus 4.5)
|
|
134
|
+
│
|
|
135
|
+
└──▶ Oracle MCP Server
|
|
136
|
+
│
|
|
137
|
+
└──▶ OCI SDK
|
|
138
|
+
│
|
|
139
|
+
├── Compute Service
|
|
140
|
+
├── Object Storage
|
|
141
|
+
├── Block Storage
|
|
142
|
+
├── Virtual Network
|
|
143
|
+
├── Database Service
|
|
144
|
+
└── Identity Service
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Authentication
|
|
148
|
+
|
|
149
|
+
The server supports two authentication methods:
|
|
150
|
+
|
|
151
|
+
1. **Session Token** (recommended for interactive use)
|
|
152
|
+
- Uses `security_token_file` from config
|
|
153
|
+
- Refreshable with `oci session refresh`
|
|
154
|
+
|
|
155
|
+
2. **API Key** (for automation)
|
|
156
|
+
- Uses RSA key pair
|
|
157
|
+
- Requires fingerprint in OCI config
|
|
158
|
+
|
|
159
|
+
## Usage Examples
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
User: List my OCI compute instances
|
|
163
|
+
|
|
164
|
+
Claude: [Uses oci_compute_list_instances tool]
|
|
165
|
+
Result:
|
|
166
|
+
- web-server-1 (VM.Standard.A1.Flex) - RUNNING
|
|
167
|
+
- db-server (VM.Standard.E2.1.Micro) - STOPPED
|
|
168
|
+
|
|
169
|
+
User: Start the db-server instance
|
|
170
|
+
|
|
171
|
+
Claude: [Uses oci_compute_instance_action with action=START]
|
|
172
|
+
Result: Instance db-server is now starting...
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Files
|
|
176
|
+
|
|
177
|
+
- `index.js` - MCP server implementation
|
|
178
|
+
- `package.json` - Dependencies
|
|
179
|
+
- `README.md` - This file
|
|
180
|
+
|
|
181
|
+
## Dependencies
|
|
182
|
+
|
|
183
|
+
- `@modelcontextprotocol/sdk` - MCP SDK
|
|
184
|
+
- `oci-sdk` - Official Oracle Cloud SDK
|
|
185
|
+
|
|
186
|
+
## Author
|
|
187
|
+
|
|
188
|
+
Matthew Karsten
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
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,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@purplesquirrel/oracle-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Oracle Cloud Infrastructure MCP Server for Claude Code",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node index.js",
|
|
9
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
10
|
+
},
|
|
11
|
+
"keywords": ["oracle", "oci", "cloud", "mcp"],
|
|
12
|
+
"author": "Matthew Karsten",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
16
|
+
"oci-sdk": "^2.122.1"
|
|
17
|
+
}
|
|
18
|
+
}
|