Skip to content
Merged
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ The following variables can be set in the environment.

| Name | Description | Default |
|-------|------------|---------------|
| `MCPSERVER_PORT` | Port to run MCP server on, if using http variant | 8089 |
| `MCPSERVER_PORT` | Port to run MCP server on, if using http variant | `8089` |
| `MCPSERVER_HOST` | Default host to run MCP server (http) | `0.0.0.0` |
| `MCPSERVER_PATH` | Default path for server endpoint | `/mcp` |
| `MCPSERVER_TOKEN` | Token to use for testing | unset |

## Examples
Expand Down
35 changes: 2 additions & 33 deletions mcpserver/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
install()

import mcpserver
from mcpserver.cli.args import populate_start_args
from mcpserver.logger import setup_logger

default_port = os.environ.get("MCPSERVER_PORT") or 8000
Expand Down Expand Up @@ -59,39 +60,7 @@ def get_parser():
formatter_class=argparse.RawTextHelpFormatter,
description="generate subsystem metadata for a cluster",
)
start.add_argument(
"--port", default=default_port, type=int, help="port to run the agent gateway"
)

# Note from V: SSE is considered deprecated (don't use it...)
start.add_argument(
"-t",
"--transport",
default="stdio",
help="Transport to use (defaults to stdin)",
choices=["stdio", "http", "sse", "streamable-http"],
)
start.add_argument("--host", default="0.0.0.0", help="Host (defaults to 0.0.0.0)")
start.add_argument(
"--tool-module",
action="append",
help="Additional tool module paths to discover from.",
default=[],
)
start.add_argument("--tool", action="append", help="Direct tool to import.", default=[])
start.add_argument("--resource", action="append", help="Direct resource to import.", default=[])
start.add_argument("--prompt", action="append", help="Direct prompt to import.", default=[])
start.add_argument("--include", help="Include tags", action="append", default=None)
start.add_argument("--exclude", help="Exclude tag", action="append", default=None)
start.add_argument("--path", help="Server path for mcp", default="/mcp")
start.add_argument("--config", help="Configuration file for server.")

start.add_argument(
"--mask-error_details",
help="Mask error details (for higher security deployments)",
action="store_true",
default=False,
)
populate_start_args(start)
return parser


Expand Down
49 changes: 49 additions & 0 deletions mcpserver/cli/args.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python

import os

default_port = os.environ.get("MCPSERVER_PORT") or 8000
default_host = os.environ.get("MCPSERVER_HOST") or "0.0.0.0"
default_path = os.environ.get("MCPSERVER_PATH") or "/mcp"


def populate_start_args(start):
"""
Given the argparse parser, add start args to it.

We provide this so a secondary library can consistently
add parsing args to its parser.
"""
start.add_argument(
"--port", default=default_port, type=int, help="port to run the agent gateway"
)

# Note from V: SSE is considered deprecated (don't use it...)
start.add_argument(
"-t",
"--transport",
default="stdio",
help="Transport to use (defaults to stdin)",
choices=["stdio", "http", "sse", "streamable-http"],
)
start.add_argument("--host", default=default_host, help=f"Host (defaults to {default_host})")
start.add_argument(
"--tool-module",
action="append",
help="Additional tool module paths to discover from.",
default=[],
)
start.add_argument("--tool", action="append", help="Direct tool to import.", default=[])
start.add_argument("--resource", action="append", help="Direct resource to import.", default=[])
start.add_argument("--prompt", action="append", help="Direct prompt to import.", default=[])
start.add_argument("--include", help="Include tags", action="append", default=None)
start.add_argument("--exclude", help="Exclude tag", action="append", default=None)
start.add_argument("--path", help="Server path for mcp", default=default_path)
start.add_argument("--config", help="Configuration file for server.")

start.add_argument(
"--mask-error_details",
help="Mask error details (for higher security deployments)",
action="store_true",
default=False,
)
42 changes: 42 additions & 0 deletions mcpserver/cli/manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from mcpserver.core.config import MCPConfig
from mcpserver.tools.manager import ToolManager

# Discover and register defaults
manager = ToolManager()
manager.register()


def get_manager(mcp, cfg):
"""
Get the common tool manager and register tools.
"""
# Add additional module paths (custom out of tree modules)
for path in cfg.discovery:
print(f"🧐 Registering additional module: {path}")
manager.register(path)

# explicit egistration
for endpoint in register(mcp, cfg):
print(f" ✅ Registered: {endpoint.name}")

# Load into the manager (tools, resources, prompts)
for tool in manager.load_tools(mcp, cfg.include, cfg.exclude):
print(f" ✅ Registered: {tool.name}")


def register(mcp, cfg: MCPConfig):
"""
Registers specific tools, prompts, and resources defined in the config.
Replaces the previous args-based register function.
"""
# Define which config lists map to which manager methods
registries = [
(cfg.tools, manager.register_tool),
(cfg.prompts, manager.register_prompt),
(cfg.resources, manager.register_resource),
]

for capability_list, register_func in registries:
for item in capability_list:
# item is a CapabilityConfig object with .path and .name
yield register_func(mcp, item.path, name=item.name)
42 changes: 3 additions & 39 deletions mcpserver/cli/start.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
from fastapi import FastAPI

from mcpserver.app import init_mcp
from mcpserver.cli.manager import get_manager
from mcpserver.core.config import MCPConfig

# These are routes also served here
from mcpserver.routes import *
from mcpserver.tools.manager import ToolManager

# Discover and register defaults
manager = ToolManager()
manager.register()


def main(args, extra, **kwargs):
Expand All @@ -23,28 +19,14 @@ def main(args, extra, **kwargs):
else:
cfg = MCPConfig.from_args(args)

# Get the tool manager and register discovered tools
mcp = init_mcp(cfg.exclude, cfg.include, args.mask_error_details)
manager = get_manager(mcp, cfg)

# Create ASGI app from MCP server
mcp_app = mcp.http_app(path=cfg.server.path)
app = FastAPI(title="MCP Server", lifespan=mcp_app.lifespan)

# Dynamic Loading of Tools
print(f"🔌 Loading tools... ")

# Add additional module paths (custom out of tree modules)
for path in cfg.discovery:
print(f"🧐 Registering additional module: {path}")
manager.register(path)

# explicit egistration
for endpoint in register(mcp, cfg):
print(f" ✅ Registered: {endpoint.name}")

# Load into the manager (tools, resources, prompts)
for tool in manager.load_tools(mcp, cfg.include, cfg.exclude):
print(f" ✅ Registered: {tool.name}")

# Mount the MCP server. Note from V: we can use mount with antother FastMCP
# mcp.run can also be replaced with mcp.run_async
app.mount("/", mcp_app)
Expand All @@ -61,21 +43,3 @@ def main(args, extra, **kwargs):
# For testing we usually control+C, let's not make it ugly
except KeyboardInterrupt:
print("🖥️ Shutting down...")


def register(mcp, cfg: MCPConfig):
"""
Registers specific tools, prompts, and resources defined in the config.
Replaces the previous args-based register function.
"""
# Define which config lists map to which manager methods
registries = [
(cfg.tools, manager.register_tool),
(cfg.prompts, manager.register_prompt),
(cfg.resources, manager.register_resource),
]

for capability_list, register_func in registries:
for item in capability_list:
# item is a CapabilityConfig object with .path and .name
yield register_func(mcp, item.path, name=item.name)
2 changes: 1 addition & 1 deletion mcpserver/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.0.11"
__version__ = "0.0.12"
AUTHOR = "Vanessa Sochat"
AUTHOR_EMAIL = "vsoch@users.noreply.github.com"
NAME = "mcp-serve"
Expand Down