Skip to content

Commit b4e800f

Browse files
Merge pull request #17 from stickerdaniel/feat/http-transport
2 parents fed12db + 17c630b commit b4e800f

File tree

14 files changed

+744
-111
lines changed

14 files changed

+744
-111
lines changed

.vscode/tasks.json

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
{
22
"version": "2.0.0",
33
"tasks": [
4+
{
5+
"label": "bunx @modelcontextprotocol/inspector",
6+
"detail": "Run the Model Context Protocol Inspector",
7+
"type": "shell",
8+
"command": "bunx",
9+
"args": ["@modelcontextprotocol/inspector"],
10+
"group": {
11+
"kind": "test",
12+
"isDefault": true
13+
},
14+
"presentation": {
15+
"reveal": "always",
16+
"panel": "new",
17+
"focus": true
18+
},
19+
"problemMatcher": []
20+
},
421
{
522
"label": "uv run pre-commit run --all-files",
623
"detail": "Run pre-commit hooks on all files",
@@ -14,7 +31,7 @@
1431
],
1532
"group": {
1633
"kind": "test",
17-
"isDefault": true
34+
"isDefault": false
1835
},
1936
"presentation": {
2037
"reveal": "never",
@@ -57,9 +74,38 @@
5774
"--no-headless",
5875
"--no-lazy-init"
5976
],
77+
"group": {
78+
"kind": "build"
79+
},
80+
"presentation": {
81+
"reveal": "always",
82+
"panel": "new",
83+
"focus": true
84+
},
85+
"problemMatcher": []
86+
},
87+
{
88+
"label": "uv run main.py --transport streamable-http --no-setup",
89+
"detail": "Start HTTP MCP server on localhost:8000/mcp",
90+
"type": "shell",
91+
"command": "uv",
92+
"args": [
93+
"run",
94+
"main.py",
95+
"--transport",
96+
"streamable-http",
97+
"--host",
98+
"127.0.0.1",
99+
"--port",
100+
"8000",
101+
"--path",
102+
"/mcp",
103+
"--no-setup"
104+
],
105+
"isBackground": true,
60106
"group": {
61107
"kind": "build",
62-
"isDefault": true
108+
"isDefault": false
63109
},
64110
"presentation": {
65111
"reveal": "always",
@@ -86,6 +132,6 @@
86132
"focus": false
87133
},
88134
"problemMatcher": []
89-
}
135+
},
90136
]
91137
}

linkedin_mcp_server/cli.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
This module handles the command-line interface and configuration management.
66
"""
77

8-
from typing import Dict, Any, List
9-
import os
108
import json
11-
import subprocess
129
import logging
10+
import os
11+
import subprocess
12+
from typing import Any, Dict, List
13+
1314
import pyperclip # type: ignore
1415

1516
from linkedin_mcp_server.config import get_config

linkedin_mcp_server/config/loaders.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ def load_from_env(config: AppConfig) -> AppConfig:
4444
# Headless mode
4545
if os.environ.get("HEADLESS") in ("0", "false", "False", "no", "No"):
4646
config.chrome.headless = False
47+
elif os.environ.get("HEADLESS") in ("1", "true", "True", "yes", "Yes"):
48+
config.chrome.headless = True
49+
50+
# Non-interactive mode
51+
if os.environ.get("NON_INTERACTIVE") in ("1", "true", "True", "yes", "Yes"):
52+
config.chrome.non_interactive = True
53+
54+
# Lazy initialization
55+
if os.environ.get("LAZY_INIT") in ("1", "true", "True", "yes", "Yes"):
56+
config.server.lazy_init = True
57+
elif os.environ.get("LAZY_INIT") in ("0", "false", "False", "no", "No"):
58+
config.server.lazy_init = False
4759

4860
return config
4961

@@ -80,9 +92,30 @@ def load_from_args(config: AppConfig) -> AppConfig:
8092

8193
parser.add_argument(
8294
"--transport",
83-
choices=["stdio", "sse"],
95+
choices=["stdio", "streamable-http"],
96+
default=None,
97+
help="Specify the transport mode (stdio or streamable-http)",
98+
)
99+
100+
parser.add_argument(
101+
"--host",
102+
type=str,
103+
default=None,
104+
help="HTTP server host (default: 127.0.0.1)",
105+
)
106+
107+
parser.add_argument(
108+
"--port",
109+
type=int,
110+
default=None,
111+
help="HTTP server port (default: 8000)",
112+
)
113+
114+
parser.add_argument(
115+
"--path",
116+
type=str,
84117
default=None,
85-
help="Specify the transport mode (stdio or sse)",
118+
help="HTTP server path (default: /mcp)",
86119
)
87120

88121
parser.add_argument(
@@ -109,6 +142,15 @@ def load_from_args(config: AppConfig) -> AppConfig:
109142
if args.transport:
110143
config.server.transport = args.transport
111144

145+
if args.host:
146+
config.server.host = args.host
147+
148+
if args.port:
149+
config.server.port = args.port
150+
151+
if args.path:
152+
config.server.path = args.path
153+
112154
if args.chromedriver:
113155
config.chrome.chromedriver_path = args.chromedriver
114156

linkedin_mcp_server/config/schema.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ class LinkedInConfig:
2626
class ServerConfig:
2727
"""MCP server configuration."""
2828

29-
transport: Literal["stdio", "sse"] = "stdio"
29+
transport: Literal["stdio", "streamable-http"] = "stdio"
3030
lazy_init: bool = True
3131
debug: bool = False
3232
setup: bool = True
33+
# HTTP transport configuration
34+
host: str = "127.0.0.1"
35+
port: int = 8000
36+
path: str = "/mcp"
3337

3438

3539
@dataclass

linkedin_mcp_server/config/secrets.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
# src/linkedin_mcp_server/config/secrets.py
2-
from typing import Dict, Optional
32
import logging
3+
from typing import Dict, Optional
4+
45
import inquirer # type: ignore
6+
57
from linkedin_mcp_server.config import get_config
8+
69
from .providers import (
710
get_credentials_from_keyring,
8-
save_credentials_to_keyring,
911
get_keyring_name,
12+
save_credentials_to_keyring,
1013
)
1114

1215
logger = logging.getLogger(__name__)

linkedin_mcp_server/drivers/chrome.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@
55
This module handles the creation and management of Chrome WebDriver instances.
66
"""
77

8+
import os
89
import sys
910
from typing import Dict, Optional
10-
import os
11+
12+
import inquirer # type: ignore
1113
from selenium import webdriver
14+
from selenium.common.exceptions import WebDriverException
1215
from selenium.webdriver.chrome.options import Options
1316
from selenium.webdriver.chrome.service import Service
14-
from selenium.common.exceptions import WebDriverException
15-
import inquirer # type: ignore
17+
1618
from linkedin_mcp_server.config import get_config
17-
from linkedin_mcp_server.config.secrets import get_credentials
1819
from linkedin_mcp_server.config.providers import clear_credentials_from_keyring
20+
from linkedin_mcp_server.config.secrets import get_credentials
1921

2022
# Global driver storage to reuse sessions
2123
active_drivers: Dict[str, webdriver.Chrome] = {}

linkedin_mcp_server/server.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
This module creates the MCP server and registers all the LinkedIn tools.
66
"""
77

8-
from typing import Dict, Any
9-
from mcp.server.fastmcp import FastMCP
8+
from typing import Any, Dict
9+
10+
from fastmcp import FastMCP
1011

1112
from linkedin_mcp_server.drivers.chrome import active_drivers
12-
from linkedin_mcp_server.tools.person import register_person_tools
1313
from linkedin_mcp_server.tools.company import register_company_tools
1414
from linkedin_mcp_server.tools.job import register_job_tools
15+
from linkedin_mcp_server.tools.person import register_person_tools
1516

1617

1718
def create_mcp_server() -> FastMCP:

linkedin_mcp_server/tools/company.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
This module provides tools for scraping LinkedIn company profiles.
66
"""
77

8-
from typing import Dict, Any, List
9-
from mcp.server.fastmcp import FastMCP
8+
from typing import Any, Dict, List
9+
10+
from fastmcp import FastMCP
1011
from linkedin_scraper import Company
1112

1213
from linkedin_mcp_server.drivers.chrome import get_or_create_driver

linkedin_mcp_server/tools/job.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
from typing import Any, Dict, List
99

10+
from fastmcp import FastMCP
1011
from linkedin_scraper import Job, JobSearch
11-
from mcp.server.fastmcp import FastMCP
1212

1313
from linkedin_mcp_server.drivers.chrome import get_or_create_driver
1414

linkedin_mcp_server/tools/person.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
This module provides tools for scraping LinkedIn person profiles.
66
"""
77

8-
from typing import Dict, Any, List
9-
from mcp.server.fastmcp import FastMCP
8+
from typing import Any, Dict, List
9+
10+
from fastmcp import FastMCP
1011
from linkedin_scraper import Person
1112

1213
from linkedin_mcp_server.drivers.chrome import get_or_create_driver

0 commit comments

Comments
 (0)