|
6 | 6 |
|
7 | 7 | """
|
8 | 8 |
|
| 9 | +import argparse |
9 | 10 | import asyncio
|
10 | 11 | import logging
|
11 | 12 | import os
|
| 13 | +import sys |
12 | 14 | import typing as t
|
13 | 15 |
|
| 16 | +from mcp.client.stdio import StdioServerParameters |
| 17 | + |
14 | 18 | from .sse_client import run_sse_client
|
| 19 | +from .sse_server import SseServerSettings, run_sse_server |
15 | 20 |
|
16 | 21 | logging.basicConfig(level=logging.DEBUG)
|
17 |
| -SSE_URL: t.Final[str] = os.getenv("SSE_URL", "") |
| 22 | +SSE_URL: t.Final[str | None] = os.getenv("SSE_URL", None) |
18 | 23 | API_ACCESS_TOKEN: t.Final[str | None] = os.getenv("API_ACCESS_TOKEN", None)
|
19 | 24 |
|
20 |
| -if not SSE_URL: |
21 |
| - raise ValueError("SSE_URL environment variable is not set") |
22 |
| - |
23 | 25 |
|
24 | 26 | def main() -> None:
|
25 | 27 | """Start the client using asyncio."""
|
26 |
| - asyncio.run(run_sse_client(SSE_URL, api_access_token=API_ACCESS_TOKEN)) |
| 28 | + parser = argparse.ArgumentParser() |
| 29 | + parser.add_argument( |
| 30 | + "command_or_url", |
| 31 | + help=( |
| 32 | + "Command or URL to connect to. When a URL, will run an SSE client " |
| 33 | + "to connect to the server, otherwise will run the command and " |
| 34 | + "connect as a stdio client. Can also be set as environment variable SSE_URL." |
| 35 | + ), |
| 36 | + nargs="?", # Required below to allow for coming form env var |
| 37 | + default=SSE_URL, |
| 38 | + ) |
| 39 | + |
| 40 | + sse_client_group = parser.add_argument_group("SSE client options") |
| 41 | + sse_client_group.add_argument( |
| 42 | + "--api-access-token", |
| 43 | + default=API_ACCESS_TOKEN, |
| 44 | + help=( |
| 45 | + "Access token Authorization header passed by the client to the SSE " |
| 46 | + "server. Can also be set as environment variable API_ACCESS_TOKEN." |
| 47 | + ), |
| 48 | + ) |
| 49 | + |
| 50 | + stdio_client_options = parser.add_argument_group("stdio client options") |
| 51 | + stdio_client_options.add_argument( |
| 52 | + "args", |
| 53 | + nargs="*", |
| 54 | + help="Arguments to the command to run to spawn the server", |
| 55 | + ) |
| 56 | + stdio_client_options.add_argument( |
| 57 | + "-e", |
| 58 | + "--env", |
| 59 | + nargs=2, |
| 60 | + action="append", |
| 61 | + metavar=("KEY", "VALUE"), |
| 62 | + help="Environment variables used when spawning the server. Can be used multiple times.", |
| 63 | + default=[], |
| 64 | + ) |
| 65 | + |
| 66 | + sse_server_group = parser.add_argument_group("SSE server options") |
| 67 | + sse_server_group.add_argument( |
| 68 | + "--sse-port", |
| 69 | + type=int, |
| 70 | + default=None, |
| 71 | + help="Port to expose an SSE server on", |
| 72 | + ) |
| 73 | + sse_server_group.add_argument( |
| 74 | + "--sse-host", |
| 75 | + default="127.0.0.1", |
| 76 | + help="Host to expose an SSE server on", |
| 77 | + ) |
| 78 | + |
| 79 | + args = parser.parse_args() |
| 80 | + |
| 81 | + if not args.command_or_url: |
| 82 | + parser.print_help() |
| 83 | + sys.exit(1) |
| 84 | + |
| 85 | + if ( |
| 86 | + SSE_URL |
| 87 | + or args.command_or_url.startswith("http://") |
| 88 | + or args.command_or_url.startswith("https://") |
| 89 | + ): |
| 90 | + # Start a client connected to the SSE server, and expose as a stdio server |
| 91 | + logging.debug("Starting SSE client and stdio server") |
| 92 | + asyncio.run(run_sse_client(args.command_or_url, api_access_token=API_ACCESS_TOKEN)) |
| 93 | + return |
| 94 | + |
| 95 | + # Start a client connected to the given command, and expose as an SSE server |
| 96 | + logging.debug("Starting stdio client and SSE server") |
| 97 | + stdio_params = StdioServerParameters( |
| 98 | + command=args.command_or_url, |
| 99 | + args=args.args, |
| 100 | + env=dict(args.env), |
| 101 | + ) |
| 102 | + sse_settings = SseServerSettings( |
| 103 | + bind_host=args.sse_host, |
| 104 | + port=args.sse_port, |
| 105 | + ) |
| 106 | + asyncio.run(run_sse_server(stdio_params, sse_settings)) |
27 | 107 |
|
28 | 108 |
|
29 | 109 | if __name__ == "__main__":
|
|
0 commit comments