Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ class Vnic(BaseModel):
"If the VNIC belongs to a VLAN as part of the Oracle Cloud VMware Solution "
"(instead of belonging to a subnet), the value of the `nsgIds` attribute is ignored. "
"Instead, the VNIC belongs to the NSGs that are associated with the VLAN itself. "
"See Vlan.",
"See Vlan."
),
)
vlan_id: Optional[str] = Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def get_networking_client():
return oci.core.VirtualNetworkClient(config, signer=signer)


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

Expand Down Expand Up @@ -78,7 +78,7 @@ def list_vcns(compartment_id: str) -> list[Vcn]:
raise


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


@mcp.tool
@mcp.tool(description="Deletes the specified VCN.")
def delete_vcn(vcn_id: str) -> Response:
try:
client = get_networking_client()
Expand All @@ -107,7 +107,7 @@ def delete_vcn(vcn_id: str) -> Response:
raise


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


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

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


@mcp.tool
@mcp.tool(description="Gets the specified subnet's information.")
def get_subnet(subnet_id: str) -> Subnet:
try:
client = get_networking_client()
Expand All @@ -174,7 +176,7 @@ def get_subnet(subnet_id: str) -> Subnet:
raise


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


@mcp.tool(
description="Lists either the network security groups in the specified compartment,"
"or those associated with the specified VLAN. You must specify either a vlanId or"
"a compartmentId, but not both. If you specify a vlanId, all other parameters are "
"ignored.",
description="Lists the network security groups in the specified compartment. "
"Optionally filter by vcn_id or vlan_id.",
)
def list_network_security_groups(
compartment_id: Annotated[str, "compartment ocid"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,13 +497,9 @@ async def test_get_vnic(self, mock_get_client):
mock_client.get_vnic.return_value = mock_get_response

async with Client(mcp) as client:
# Expect ToolError due to schema validation issue in installed package
with pytest.raises(ToolError):
call_tool_result = await client.call_tool(
"get_vnic", {"vnic_id": "vnic1"}
)
result = call_tool_result.structured_content
assert result["id"] == "vnic1"
call_tool_result = await client.call_tool("get_vnic", {"vnic_id": "vnic1"})
result = call_tool_result.structured_content
assert result["id"] == "vnic1"


class TestServer:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ def search_resources(
try:
client = get_search_client()

oci.identity.models.Compartment

response: oci.response.Response = None
has_next_page = True
next_page: str = None
Expand Down
150 changes: 143 additions & 7 deletions tests/e2e/features/mcphost.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"mcpServers": {
"oracle-oci-api-mcp-server": {
"oracle-oci-cloud-guard-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"oracle.oci-api-mcp-server"
"oracle.oci-cloud-guard-mcp-server"
],
"env": {
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
Expand All @@ -20,14 +20,14 @@
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-cloud-guard-mcp-server": {
"oracle-oci-compute-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"oracle.oci-cloud-guard-mcp-server"
"oracle.oci-compute-mcp-server"
],
"env": {
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
Expand All @@ -40,14 +40,14 @@
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-compute-mcp-server": {
"oracle-oci-compute-instance-agent-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"oracle.oci-compute-mcp-server"
"oracle.oci-compute-instance-agent-mcp-server"
],
"env": {
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
Expand Down Expand Up @@ -142,16 +142,152 @@
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-monitoring-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"oracle.oci-monitoring-mcp-server"
],
"env": {
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
"HTTP_PROXY": "http://127.0.0.1:5000",
"HTTPS_PROXY": "http://127.0.0.1:5000",
"OCI_SDK_CERT_BUNDLE": "False",
"PYTHONHTTPSVERIFY": "0",
"OCI_SKIP_SSL_VERIFICATION": "True",
"REQUESTS_CA_BUNDLE": "",
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-networking-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"oracle.oci-networking-mcp-server"
],
"env": {
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
"HTTP_PROXY": "http://127.0.0.1:5000",
"HTTPS_PROXY": "http://127.0.0.1:5000",
"OCI_SDK_CERT_BUNDLE": "False",
"PYTHONHTTPSVERIFY": "0",
"OCI_SKIP_SSL_VERIFICATION": "True",
"REQUESTS_CA_BUNDLE": "",
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-network-load-balancer-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"python",
"-c",
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_network_load_balancer_mcp_server.server import main; main()"
],
"env": {
"PYTHONPATH": "../../../src/oci-network-load-balancer-mcp-server:mocks",
"PYTHONNOUSERSITE": "0",
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
"HTTP_PROXY": "http://127.0.0.1:5000",
"HTTPS_PROXY": "http://127.0.0.1:5000",
"OCI_SDK_CERT_BUNDLE": "False",
"PYTHONHTTPSVERIFY": "0",
"OCI_SKIP_SSL_VERIFICATION": "True",
"REQUESTS_CA_BUNDLE": "",
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-object-storage-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"oracle.oci-object-storage-mcp-server"
"python",
"-c",
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_object_storage_mcp_server.server import main; main()"
],
"env": {
"PYTHONPATH": "../../../src/oci-object-storage-mcp-server:mocks",
"PYTHONNOUSERSITE": "0",
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
"HTTP_PROXY": "http://127.0.0.1:5000",
"HTTPS_PROXY": "http://127.0.0.1:5000",
"OCI_SDK_CERT_BUNDLE": "False",
"PYTHONHTTPSVERIFY": "0",
"OCI_SKIP_SSL_VERIFICATION": "True",
"REQUESTS_CA_BUNDLE": "",
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-registry-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"oracle.oci-registry-mcp-server"
],
"env": {
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
"HTTP_PROXY": "http://127.0.0.1:5000",
"HTTPS_PROXY": "http://127.0.0.1:5000",
"OCI_SDK_CERT_BUNDLE": "False",
"PYTHONHTTPSVERIFY": "0",
"OCI_SKIP_SSL_VERIFICATION": "True",
"REQUESTS_CA_BUNDLE": "",
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-resource-search-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"python",
"-c",
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_resource_search_mcp_server.server import main; main()"
],
"env": {
"PYTHONPATH": "../../../src/oci-resource-search-mcp-server:mocks",
"PYTHONNOUSERSITE": "0",
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
"HTTP_PROXY": "http://127.0.0.1:5000",
"HTTPS_PROXY": "http://127.0.0.1:5000",
"OCI_SDK_CERT_BUNDLE": "False",
"PYTHONHTTPSVERIFY": "0",
"OCI_SKIP_SSL_VERIFICATION": "True",
"REQUESTS_CA_BUNDLE": "",
"CURL_CA_BUNDLE": ""
}
},
"oracle-oci-usage-mcp-server": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"python",
"-c",
"import sys; sys.path.insert(0, 'mocks'); import sitecustomize; from oracle.oci_usage_mcp_server.server import main; main()"
],
"env": {
"PYTHONPATH": "../../../src/oci-usage-mcp-server:mocks",
"PYTHONNOUSERSITE": "0",
"OCI_CONFIG_FILE": "${env:OCI_CONFIG_FILE}",
"HTTP_PROXY": "http://127.0.0.1:5000",
"HTTPS_PROXY": "http://127.0.0.1:5000",
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/features/mocks/mock_oci_server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (c) 2025, Oracle and/or its affiliates.
Copyright (c) 2026, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at
https://oss.oracle.com/licenses/upl.
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/features/mocks/proxy_shim.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (c) 2025, Oracle and/or its affiliates.
Copyright (c) 2026, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at
https://oss.oracle.com/licenses/upl.
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/features/mocks/services/cloud_guard_data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (c) 2025, Oracle and/or its affiliates.
Copyright (c) 2026, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at
https://oss.oracle.com/licenses/upl.
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/features/mocks/services/cloud_guard_routes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (c) 2025, Oracle and/or its affiliates.
Copyright (c) 2026, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at
https://oss.oracle.com/licenses/upl.
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/features/mocks/services/compute_data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright (c) 2025, Oracle and/or its affiliates.
Copyright (c) 2026, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at
https://oss.oracle.com/licenses/upl.
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Copyright (c) 2026, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v1.0 as shown at
https://oss.oracle.com/licenses/upl.
"""

from datetime import datetime, timezone

# CamelCase keys as required

# Stored commands created via the mock
INSTANCE_AGENT_COMMANDS = []

# Pre-populated command executions (summaries). Tests can list these even
# before creating new ones.
INSTANCE_AGENT_EXECUTIONS = [
{
"instanceAgentCommandId": "ocid1.instanceagentcommand.oc1..mock-cmd-1",
"instanceId": "ocid1.instance.oc1..mock-uuid-1",
"deliveryState": "VISIBLE",
"lifecycleState": "SUCCEEDED",
"timeCreated": "2026-01-13T10:00:00Z",
"timeUpdated": "2026-01-13T10:00:10Z",
"sequenceNumber": 100,
"displayName": "echo-hello",
"content": {
"outputType": "TEXT",
"exitCode": 0,
"message": "Execution successful",
"text": "hello",
"textSha256": "abc123",
},
}
]


def now_rfc3339():
return (
datetime.now(timezone.utc)
.replace(microsecond=0)
.isoformat()
.replace("+00:00", "Z")
)
Loading
Loading