Make AI features (AI Copilot + MCP) optional via [ai-features] extra

- Move fastmcp from core requirements.txt to mcp-requirements.txt
- Add MCP_AVAILABLE feature flag in agent/__init__.py (graceful degradation)
- Guard MCP imports/registration in server.py and tasks.py
- Replace ai-copilot/mcp/ai-support extras with single ai-features extra
- Add stub MCP routes returning 501 when MCP is not installed
- Add gns3server-uninstall-ai-features CLI command
- Remove old gns3server-uninstall-ai-copilot command
- Update all error messages and docs to reference ai-features

Closes #2794
This commit is contained in:
YueGuobin 2026-06-26 00:17:02 +08:00
parent 58d3055dd3
commit 292b60efaa
No known key found for this signature in database
11 changed files with 117 additions and 58 deletions

View File

@ -58,11 +58,11 @@ python3 -m pip install gns3-server
GNS3 server supports optional features that can be installed as needed:
**AI Copilot** (Optional):
**AI Features** (Optional — includes AI Copilot and MCP):
```shell
python3 -m pip install gns3-server[ai-copilot]
python3 -m pip install gns3-server[ai-features]
```
AI-powered assistant for network topology design and automation.
AI-powered assistant for network topology design, automation, and MCP protocol support for AI agent integration.
**Development** (For contributors):
```shell
@ -78,7 +78,7 @@ Browser-based packet capture analysis using Wireshark in a Docker container.
**Combination Installation**:
You can install multiple optional features together:
```shell
python3 -m pip install gns3-server[ai-copilot,dev]
python3 -m pip install gns3-server[ai-features,dev]
```
**Why optional?**
@ -89,17 +89,15 @@ python3 -m pip install gns3-server[ai-copilot,dev]
**Note:** If you install without optional extras, the server will work normally but optional features will be disabled. You can add features later by running the appropriate install command.
**Uninstalling AI Copilot:**
**Uninstalling AI Features:**
To remove AI Copilot dependencies:
To remove AI Features dependencies (AI Copilot + MCP):
```shell
gns3server-uninstall-ai-copilot
gns3server-uninstall-ai-features
```
This will remove all AI Copilot dependencies while keeping the core functionality intact. The server will continue to work, but AI features will return a 501 (Not Implemented) status code.
The downside of this method is you will have to manually install all dependencies (see below).
This will remove all AI Copilot and MCP dependencies while keeping the core functionality intact. The server will continue to work, but AI features will be disabled.
Please see our [documentation](https://docs.gns3.com/docs/getting-started/installation/linux) for more details.
@ -137,7 +135,7 @@ python3 -m gns3server
**For AI Copilot development**, install with additional dependencies:
```shell
python3 -m pip install .[ai-copilot,dev]
python3 -m pip install .[ai-features,dev]
```
**For development (tests and linting)**:

View File

@ -1,7 +1,7 @@
# ==============================================================================
# GNS3 Copilot AI Agent Dependencies
# ==============================================================================
# Install with: pip install gns3-server[ai-copilot]
# Install with: pip install gns3-server[ai-features]
# Or directly: pip install -r ai-requirements.txt
# ==============================================================================

View File

@ -104,7 +104,7 @@ source venv/bin/activate
# pip install -e . -i https://mirrors.aliyun.com/pypi/simple/
pip install -e . && gns3server-web-wireshark-setup
pip install -e .[ai-copilot]
pip install -e .[ai-features]
pip install -e .[dev]
```
@ -114,10 +114,10 @@ Run the server:
python3 -m gns3server
```
## Optional: Install AI Copilot Development Dependencies
## Optional: Install AI Features Development Dependencies
```bash
python3 -m pip install .[ai-copilot,dev]
python3 -m pip install .[ai-features,dev]
```
## Optional: Expand LVM Root Partition

View File

@ -15,14 +15,15 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Agent module with optional AI Copilot support.
Agent module with optional AI Copilot and MCP support.
This module provides the AI Copilot functionality as an optional feature.
If the AI dependencies are not installed, the module will be disabled but
will not prevent the server from starting.
This module provides the AI Copilot and MCP (Model Context Protocol)
functionality as optional features. If the respective dependencies are
not installed, the affected features will be disabled but will not
prevent the server from starting.
Installation:
pip install gns3-server[ai-copilot]
pip install gns3-server[ai-features] # Install all AI features
"""
import logging
@ -49,7 +50,8 @@ except ImportError as e:
# AI dependencies not installed, disable AI Copilot feature
logging.warning(
f"AI Copilot dependencies not installed: {e}. "
"AI features will be disabled. Install with: pip install gns3-server[ai-copilot]"
"AI features will be disabled. "
"Install with: pip install gns3-server[ai-features]"
)
AI_COPILOT_AVAILABLE = False
@ -63,7 +65,7 @@ except ImportError as e:
"""
raise RuntimeError(
"AI Copilot is not available. "
"Install AI dependencies with: pip install gns3-server[ai-copilot]"
"Install AI dependencies with: pip install gns3-server[ai-features]"
)
class ProjectAgentManager:
@ -74,12 +76,30 @@ except ImportError as e:
def __init__(self):
raise RuntimeError(
"AI Copilot is not available. "
"Install AI dependencies with: pip install gns3-server[ai-copilot]"
"Install AI dependencies with: pip install gns3-server[ai-features]"
)
# Feature flag: MCP (Model Context Protocol) is available
MCP_AVAILABLE = False
# Try to import MCP dependencies
try:
import mcp.server.fastmcp # noqa: F401 — test import only
MCP_AVAILABLE = True
except ImportError:
# MCP dependencies not installed, disable MCP feature
logging.warning(
"MCP dependencies not installed. "
"MCP features will be disabled. "
"Install with: pip install gns3-server[ai-features]"
)
MCP_AVAILABLE = False
__all__ = [
"AI_COPILOT_AVAILABLE",
"MCP_AVAILABLE",
"get_project_agent_manager",
"ProjectAgentManager",
]

View File

@ -39,7 +39,7 @@ else:
async def ai_not_available(path: str = ""):
raise HTTPException(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="AI Copilot is not available. Install AI dependencies with: pip install gns3-server[ai-copilot]"
detail="AI Copilot is not available. Install AI dependencies with: pip install gns3-server[ai-features]"
)
from . import controller

View File

@ -45,9 +45,26 @@ from gns3server.controller.controller_error import (
from gns3server.api.routes import controller, index
from gns3server.api.routes.compute import compute_api
from gns3server.api.routes import mcp
from gns3server.core import tasks
# MCP is an optional feature — import only if dependencies are installed
from gns3server.agent import MCP_AVAILABLE
if MCP_AVAILABLE:
from gns3server.api.routes import mcp
_mcp_router = mcp.router
else:
from fastapi import APIRouter
_mcp_router = APIRouter(prefix="/mcp", tags=["MCP"])
@_mcp_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"])
async def mcp_not_available(path: str = ""):
raise HTTPException(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="MCP is not available. Install AI dependencies with: pip install gns3-server[ai-features]"
)
import logging
log = logging.getLogger(__name__)
@ -76,7 +93,9 @@ def get_application() -> FastAPI:
application.include_router(controller.router, prefix="/v3")
application.mount("/static", StaticFiles(packages=[('gns3server', 'static')], html=True), name="static")
application.mount("/v3/compute", compute_api, name="compute")
application.include_router(mcp.router, prefix="/v3", tags=["MCP"])
# Register MCP routes (stub returns 501 if MCP dependencies are not installed)
application.include_router(_mcp_router, prefix="/v3", tags=["MCP"])
return application
@ -84,7 +103,8 @@ def get_application() -> FastAPI:
app = get_application()
# Register MCP SSE transport routes (Starlette-level, for raw ASGI access)
mcp.register_starlette_routes(app)
if MCP_AVAILABLE:
mcp.register_starlette_routes(app)
# Monkey Patch uvicorn signal handler to detect the application is shutting down
app.state.exiting = False

View File

@ -84,9 +84,12 @@ async def startup(app: FastAPI) -> None:
m = module.instance()
m.port_manager = PortManager.instance()
# Mark MCP server as ready to accept connections
from gns3server.api.routes.mcp import set_mcp_server_ready
set_mcp_server_ready(True)
# Mark MCP server as ready to accept connections (if MCP is available)
from gns3server.agent import MCP_AVAILABLE
if MCP_AVAILABLE:
from gns3server.api.routes.mcp import set_mcp_server_ready
set_mcp_server_ready(True)
log.info("GNS3 server startup completed")

View File

@ -1,10 +1,10 @@
#!/usr/bin/env python3
"""
Uninstall AI Copilot dependencies.
Uninstall AI Features dependencies (AI Copilot + MCP).
Usage:
gns3server-uninstall-ai-copilot
gns3server-uninstall-ai-copilot -y
gns3server-uninstall-ai-features
gns3server-uninstall-ai-features -y
"""
import os
@ -13,38 +13,50 @@ import subprocess
import argparse
def get_ai_packages():
"""Read packages from ai-requirements.txt."""
# Find the requirements file
def _find_base_dir():
"""Find the project root directory."""
if hasattr(sys, '_MEIPASS'):
# PyInstaller bundle
base_dir = os.path.dirname(sys.executable)
else:
# __file__ = gns3server/utils/uninstall_ai_copilot.py
# Need to go up 2 levels to reach project root
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
return os.path.dirname(sys.executable)
return os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
requirements_file = os.path.join(base_dir, "ai-requirements.txt")
def _read_requirements(filename):
"""Read packages from a requirements file."""
base_dir = _find_base_dir()
filepath = os.path.join(base_dir, filename)
packages = []
with open(requirements_file, "r") as f:
with open(filepath, "r") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
# Remove version specifiers
package = line.split(">=")[0].split("==")[0].split("~=")[0]
packages.append(package)
return packages
def get_ai_packages():
"""Read packages from all AI features requirements files."""
packages = []
packages.extend(_read_requirements("ai-requirements.txt"))
packages.extend(_read_requirements("mcp-requirements.txt"))
# Remove duplicates while preserving order
seen = set()
unique = []
for pkg in packages:
if pkg not in seen:
seen.add(pkg)
unique.append(pkg)
return unique
def uninstall(packages, yes=False):
"""Uninstall packages."""
if not packages:
print("No packages found to uninstall.")
return
print(f"Found {len(packages)} AI Copilot dependencies:")
print(f"Found {len(packages)} AI Features dependencies:")
for pkg in packages:
print(f" - {pkg}")
print()
@ -70,13 +82,13 @@ def uninstall(packages, yes=False):
except Exception as e:
print(f" Error removing {package}: {e}")
print("\nAI Copilot dependencies have been uninstalled.")
print("You can reinstall them with: pip install gns3-server[ai-copilot]")
print("\nAI Features dependencies have been uninstalled.")
print("You can reinstall them with: pip install gns3-server[ai-features]")
def main():
parser = argparse.ArgumentParser(
description="Uninstall AI Copilot dependencies"
description="Uninstall AI Features dependencies (AI Copilot + MCP)"
)
parser.add_argument(
"-y", "--yes", action="store_true",

8
mcp-requirements.txt Normal file
View File

@ -0,0 +1,8 @@
# ==============================================================================
# GNS3 MCP (Model Context Protocol) Service Dependencies
# ==============================================================================
# Install with: pip install gns3-server[ai-features]
# Or directly: pip install -r mcp-requirements.txt
# ==============================================================================
fastmcp>=3.4.0

View File

@ -38,8 +38,8 @@ dependencies = {file = "requirements.txt"}
# Development dependencies
dev = {file = ['dev-requirements.txt']}
# Optional components (can be installed individually or combined)
ai-copilot = {file = ['ai-requirements.txt']}
# AI features bundle — installs both AI Copilot and MCP dependencies
ai-features = {file = ['ai-requirements.txt', 'mcp-requirements.txt']}
# terraform = {file = ['terraform-requirements.txt']} # Future component
[project.urls]
@ -50,8 +50,8 @@ ai-copilot = {file = ['ai-requirements.txt']}
[project.scripts]
gns3server = "gns3server.main:main"
gns3vmnet = "gns3server.utils.vmnet:main"
gns3server-uninstall-ai-copilot = "gns3server.utils.uninstall_ai_copilot:main"
gns3server-web-wireshark-setup = "gns3server.agent.web_wireshark.setup_wireshark_image:main"
gns3server-uninstall-ai-features = "gns3server.utils.uninstall_ai_features:main"
[tool.setuptools]
packages = ["gns3server"]

View File

@ -31,19 +31,17 @@ typing-extensions>=4.15.0
requests>=2.34.2
urllib3>=2.7.0
# MCP (Model Context Protocol) dependencies
fastmcp>=3.4.0
# ==============================================================================
# File type detection
python-magic>=0.4.27
# AI Copilot Optional Dependencies
# Optional AI Features (AI Copilot + MCP)
# ==============================================================================
# AI Copilot features are now optional. Install with:
# pip install gns3-server[ai-copilot]
# AI Copilot and MCP features are now optional. Install with:
# pip install gns3-server[ai-features]
# Or:
# pip install -r ai-requirements.txt
# pip install -r mcp-requirements.txt
#
# This reduces installation size and supports restricted environments where
# AI dependencies may not be allowed.