Skip to content

Commit fb7350b

Browse files
committed
Add compute instance agent, object storage, monitoring, usage, resource search, registry, nlb, and networking e2e tests
1 parent 9748597 commit fb7350b

40 files changed

+2116
-115
lines changed

src/oci-networking-mcp-server/oracle/oci_networking_mcp_server/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ class Vnic(BaseModel):
907907
"If the VNIC belongs to a VLAN as part of the Oracle Cloud VMware Solution "
908908
"(instead of belonging to a subnet), the value of the `nsgIds` attribute is ignored. "
909909
"Instead, the VNIC belongs to the NSGs that are associated with the VLAN itself. "
910-
"See Vlan.",
910+
"See Vlan."
911911
),
912912
)
913913
vlan_id: Optional[str] = Field(

src/oci-networking-mcp-server/oracle/oci_networking_mcp_server/server.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def get_networking_client():
4949
return oci.core.VirtualNetworkClient(config, signer=signer)
5050

5151

52-
@mcp.tool
52+
@mcp.tool(description="Lists the VCNs in the specified compartment.")
5353
def list_vcns(compartment_id: str) -> list[Vcn]:
5454
vcns: list[Vcn] = []
5555

@@ -78,7 +78,7 @@ def list_vcns(compartment_id: str) -> list[Vcn]:
7878
raise
7979

8080

81-
@mcp.tool
81+
@mcp.tool(description="Gets the specified VCN's information.")
8282
def get_vcn(vcn_id: str) -> Vcn:
8383
try:
8484
client = get_networking_client()
@@ -93,7 +93,7 @@ def get_vcn(vcn_id: str) -> Vcn:
9393
raise
9494

9595

96-
@mcp.tool
96+
@mcp.tool(description="Deletes the specified VCN.")
9797
def delete_vcn(vcn_id: str) -> Response:
9898
try:
9999
client = get_networking_client()
@@ -107,7 +107,7 @@ def delete_vcn(vcn_id: str) -> Response:
107107
raise
108108

109109

110-
@mcp.tool
110+
@mcp.tool(description="Creates a new VCN.")
111111
def create_vcn(compartment_id: str, cidr_block: str, display_name: str) -> Vcn:
112112
try:
113113
client = get_networking_client()
@@ -128,7 +128,9 @@ def create_vcn(compartment_id: str, cidr_block: str, display_name: str) -> Vcn:
128128
raise
129129

130130

131-
@mcp.tool
131+
@mcp.tool(
132+
description="Lists the subnets in the specified compartment. Optionally filter by VCN."
133+
)
132134
def list_subnets(compartment_id: str, vcn_id: str = None) -> list[Subnet]:
133135
subnets: list[Subnet] = []
134136

@@ -159,7 +161,7 @@ def list_subnets(compartment_id: str, vcn_id: str = None) -> list[Subnet]:
159161
raise
160162

161163

162-
@mcp.tool
164+
@mcp.tool(description="Gets the specified subnet's information.")
163165
def get_subnet(subnet_id: str) -> Subnet:
164166
try:
165167
client = get_networking_client()
@@ -174,7 +176,7 @@ def get_subnet(subnet_id: str) -> Subnet:
174176
raise
175177

176178

177-
@mcp.tool
179+
@mcp.tool(description="Creates a new subnet.")
178180
def create_subnet(
179181
vcn_id: str, compartment_id: str, cidr_block: str, display_name: str
180182
) -> Subnet:
@@ -253,10 +255,8 @@ def get_security_list(security_list_id: Annotated[str, "security list id"]):
253255

254256

255257
@mcp.tool(
256-
description="Lists either the network security groups in the specified compartment,"
257-
"or those associated with the specified VLAN. You must specify either a vlanId or"
258-
"a compartmentId, but not both. If you specify a vlanId, all other parameters are "
259-
"ignored.",
258+
description="Lists the network security groups in the specified compartment. "
259+
"Optionally filter by vcn_id or vlan_id.",
260260
)
261261
def list_network_security_groups(
262262
compartment_id: Annotated[str, "compartment ocid"],

src/oci-networking-mcp-server/oracle/oci_networking_mcp_server/tests/test_networking_tools.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -497,13 +497,9 @@ async def test_get_vnic(self, mock_get_client):
497497
mock_client.get_vnic.return_value = mock_get_response
498498

499499
async with Client(mcp) as client:
500-
# Expect ToolError due to schema validation issue in installed package
501-
with pytest.raises(ToolError):
502-
call_tool_result = await client.call_tool(
503-
"get_vnic", {"vnic_id": "vnic1"}
504-
)
505-
result = call_tool_result.structured_content
506-
assert result["id"] == "vnic1"
500+
call_tool_result = await client.call_tool("get_vnic", {"vnic_id": "vnic1"})
501+
result = call_tool_result.structured_content
502+
assert result["id"] == "vnic1"
507503

508504

509505
class TestServer:

src/oci-resource-search-mcp-server/oracle/oci_resource_search_mcp_server/server.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,6 @@ def search_resources(
119119
try:
120120
client = get_search_client()
121121

122-
oci.identity.models.Compartment
123-
124122
response: oci.response.Response = None
125123
has_next_page = True
126124
next_page: str = None

tests/e2e/features/mcphost.json

Lines changed: 143 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"mcpServers": {
3-
"oracle-oci-api-mcp-server": {
3+
"oracle-oci-cloud-guard-mcp-server": {
44
"disabled": false,
55
"timeout": 60,
66
"type": "stdio",
77
"command": "uv",
88
"args": [
99
"run",
10-
"oracle.oci-api-mcp-server"
10+
"oracle.oci-cloud-guard-mcp-server"
1111
],
1212
"env": {
1313
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
@@ -20,14 +20,14 @@
2020
"CURL_CA_BUNDLE": ""
2121
}
2222
},
23-
"oracle-oci-cloud-guard-mcp-server": {
23+
"oracle-oci-compute-mcp-server": {
2424
"disabled": false,
2525
"timeout": 60,
2626
"type": "stdio",
2727
"command": "uv",
2828
"args": [
2929
"run",
30-
"oracle.oci-cloud-guard-mcp-server"
30+
"oracle.oci-compute-mcp-server"
3131
],
3232
"env": {
3333
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
@@ -40,14 +40,14 @@
4040
"CURL_CA_BUNDLE": ""
4141
}
4242
},
43-
"oracle-oci-compute-mcp-server": {
43+
"oracle-oci-compute-instance-agent-mcp-server": {
4444
"disabled": false,
4545
"timeout": 60,
4646
"type": "stdio",
4747
"command": "uv",
4848
"args": [
4949
"run",
50-
"oracle.oci-compute-mcp-server"
50+
"oracle.oci-compute-instance-agent-mcp-server"
5151
],
5252
"env": {
5353
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
@@ -142,16 +142,152 @@
142142
"CURL_CA_BUNDLE": ""
143143
}
144144
},
145+
"oracle-oci-monitoring-mcp-server": {
146+
"disabled": false,
147+
"timeout": 60,
148+
"type": "stdio",
149+
"command": "uv",
150+
"args": [
151+
"run",
152+
"oracle.oci-monitoring-mcp-server"
153+
],
154+
"env": {
155+
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
156+
"HTTP_PROXY": "http://127.0.0.1:5000",
157+
"HTTPS_PROXY": "http://127.0.0.1:5000",
158+
"OCI_SDK_CERT_BUNDLE": "False",
159+
"PYTHONHTTPSVERIFY": "0",
160+
"OCI_SKIP_SSL_VERIFICATION": "True",
161+
"REQUESTS_CA_BUNDLE": "",
162+
"CURL_CA_BUNDLE": ""
163+
}
164+
},
165+
"oracle-oci-networking-mcp-server": {
166+
"disabled": false,
167+
"timeout": 60,
168+
"type": "stdio",
169+
"command": "uv",
170+
"args": [
171+
"run",
172+
"oracle.oci-networking-mcp-server"
173+
],
174+
"env": {
175+
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
176+
"HTTP_PROXY": "http://127.0.0.1:5000",
177+
"HTTPS_PROXY": "http://127.0.0.1:5000",
178+
"OCI_SDK_CERT_BUNDLE": "False",
179+
"PYTHONHTTPSVERIFY": "0",
180+
"OCI_SKIP_SSL_VERIFICATION": "True",
181+
"REQUESTS_CA_BUNDLE": "",
182+
"CURL_CA_BUNDLE": ""
183+
}
184+
},
185+
"oracle-oci-network-load-balancer-mcp-server": {
186+
"disabled": false,
187+
"timeout": 60,
188+
"type": "stdio",
189+
"command": "uv",
190+
"args": [
191+
"run",
192+
"python",
193+
"-c",
194+
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_network_load_balancer_mcp_server.server import main; main()"
195+
],
196+
"env": {
197+
"PYTHONPATH": "../../../src/oci-network-load-balancer-mcp-server:mocks",
198+
"PYTHONNOUSERSITE": "0",
199+
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
200+
"HTTP_PROXY": "http://127.0.0.1:5000",
201+
"HTTPS_PROXY": "http://127.0.0.1:5000",
202+
"OCI_SDK_CERT_BUNDLE": "False",
203+
"PYTHONHTTPSVERIFY": "0",
204+
"OCI_SKIP_SSL_VERIFICATION": "True",
205+
"REQUESTS_CA_BUNDLE": "",
206+
"CURL_CA_BUNDLE": ""
207+
}
208+
},
145209
"oracle-oci-object-storage-mcp-server": {
146210
"disabled": false,
147211
"timeout": 60,
148212
"type": "stdio",
149213
"command": "uv",
150214
"args": [
151215
"run",
152-
"oracle.oci-object-storage-mcp-server"
216+
"python",
217+
"-c",
218+
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_object_storage_mcp_server.server import main; main()"
219+
],
220+
"env": {
221+
"PYTHONPATH": "../../../src/oci-object-storage-mcp-server:mocks",
222+
"PYTHONNOUSERSITE": "0",
223+
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
224+
"HTTP_PROXY": "http://127.0.0.1:5000",
225+
"HTTPS_PROXY": "http://127.0.0.1:5000",
226+
"OCI_SDK_CERT_BUNDLE": "False",
227+
"PYTHONHTTPSVERIFY": "0",
228+
"OCI_SKIP_SSL_VERIFICATION": "True",
229+
"REQUESTS_CA_BUNDLE": "",
230+
"CURL_CA_BUNDLE": ""
231+
}
232+
},
233+
"oracle-oci-registry-mcp-server": {
234+
"disabled": false,
235+
"timeout": 60,
236+
"type": "stdio",
237+
"command": "uv",
238+
"args": [
239+
"run",
240+
"oracle.oci-registry-mcp-server"
241+
],
242+
"env": {
243+
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
244+
"HTTP_PROXY": "http://127.0.0.1:5000",
245+
"HTTPS_PROXY": "http://127.0.0.1:5000",
246+
"OCI_SDK_CERT_BUNDLE": "False",
247+
"PYTHONHTTPSVERIFY": "0",
248+
"OCI_SKIP_SSL_VERIFICATION": "True",
249+
"REQUESTS_CA_BUNDLE": "",
250+
"CURL_CA_BUNDLE": ""
251+
}
252+
},
253+
"oracle-oci-resource-search-mcp-server": {
254+
"disabled": false,
255+
"timeout": 60,
256+
"type": "stdio",
257+
"command": "uv",
258+
"args": [
259+
"run",
260+
"python",
261+
"-c",
262+
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_resource_search_mcp_server.server import main; main()"
263+
],
264+
"env": {
265+
"PYTHONPATH": "../../../src/oci-resource-search-mcp-server:mocks",
266+
"PYTHONNOUSERSITE": "0",
267+
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
268+
"HTTP_PROXY": "http://127.0.0.1:5000",
269+
"HTTPS_PROXY": "http://127.0.0.1:5000",
270+
"OCI_SDK_CERT_BUNDLE": "False",
271+
"PYTHONHTTPSVERIFY": "0",
272+
"OCI_SKIP_SSL_VERIFICATION": "True",
273+
"REQUESTS_CA_BUNDLE": "",
274+
"CURL_CA_BUNDLE": ""
275+
}
276+
},
277+
"oracle-oci-usage-mcp-server": {
278+
"disabled": false,
279+
"timeout": 60,
280+
"type": "stdio",
281+
"command": "uv",
282+
"args": [
283+
"run",
284+
"python",
285+
"-c",
286+
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_usage_mcp_server.server import main; main()"
153287
],
154288
"env": {
289+
"PYTHONPATH": "../../../src/oci-usage-mcp-server:mocks",
290+
"PYTHONNOUSERSITE": "0",
155291
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
156292
"HTTP_PROXY": "http://127.0.0.1:5000",
157293
"HTTPS_PROXY": "http://127.0.0.1:5000",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""
2+
Copyright (c) 2025, Oracle and/or its affiliates.
3+
Licensed under the Universal Permissive License v1.0 as shown at
4+
https://oss.oracle.com/licenses/upl.
5+
"""
6+
7+
from datetime import datetime, timezone
8+
9+
# CamelCase keys as required
10+
11+
# Stored commands created via the mock
12+
INSTANCE_AGENT_COMMANDS = []
13+
14+
# Pre-populated command executions (summaries). Tests can list these even
15+
# before creating new ones.
16+
INSTANCE_AGENT_EXECUTIONS = [
17+
{
18+
"instanceAgentCommandId": "ocid1.instanceagentcommand.oc1..mock-cmd-1",
19+
"instanceId": "ocid1.instance.oc1..mock-uuid-1",
20+
"deliveryState": "VISIBLE",
21+
"lifecycleState": "SUCCEEDED",
22+
"timeCreated": "2026-01-13T10:00:00Z",
23+
"timeUpdated": "2026-01-13T10:00:10Z",
24+
"sequenceNumber": 100,
25+
"displayName": "echo-hello",
26+
"content": {
27+
"outputType": "TEXT",
28+
"exitCode": 0,
29+
"message": "Execution successful",
30+
"text": "hello",
31+
"textSha256": "abc123",
32+
},
33+
}
34+
]
35+
36+
37+
def now_rfc3339():
38+
return (
39+
datetime.now(timezone.utc)
40+
.replace(microsecond=0)
41+
.isoformat()
42+
.replace("+00:00", "Z")
43+
)

0 commit comments

Comments
 (0)