Skip to content

Commit bd7ffd8

Browse files
authored
fix(connector): issue #96 normalize HTTP headers to lowercase to prevent duplicates (#98)
* fix(connector): normalize HTTP headers to lowercase to prevent duplicates Fixes #96 Convert all HTTP header names to lowercase per RFC 7230. This prevents duplicate headers when servers respond with 'mcp-protocol-version' and the client adds 'MCP-Protocol-Version', which caused 400 Bad Request errors in Express-based servers. * chore: formating * chore: small improvement for commit message * chore(release): bump version to 0.18.2
1 parent e635364 commit bd7ffd8

File tree

8 files changed

+591
-376
lines changed

8 files changed

+591
-376
lines changed

DEV.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ To create a new release:
5858

5959
2. Commit the changes:
6060
```bash
61-
git add .
62-
git commit -m "Bump version to X.Y.Z"
61+
git add -A
62+
git commit -m "chore(release): bump version to X.Y.Z"
6363
```
6464

6565
3. Push the changes and create a tag:

cli-package/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "ollmcp"
3-
version = "0.18.1"
3+
version = "0.18.2"
44
description = "CLI for MCP Client for Ollama - An easy-to-use command for interacting with Ollama through MCP"
55
readme = "README.md"
66
requires-python = ">=3.10"
@@ -9,7 +9,7 @@ authors = [
99
{name = "Jonathan Löwenstern"}
1010
]
1111
dependencies = [
12-
"mcp-client-for-ollama==0.18.1"
12+
"mcp-client-for-ollama==0.18.2"
1313
]
1414

1515
[project.scripts]

mcp_client_for_ollama/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""MCP Client for Ollama package."""
22

3-
__version__ = "0.18.1"
3+
__version__ = "0.18.2"

mcp_client_for_ollama/server/connector.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ def _get_headers_from_server(self, server: Dict[str, Any]) -> Dict[str, str]:
407407
server: Server configuration dictionary
408408
409409
Returns:
410-
Dictionary of headers
410+
Dictionary of headers with lowercase keys
411411
"""
412412
# Try to get headers directly from server dict
413413
headers = server.get("headers", {})
@@ -416,10 +416,13 @@ def _get_headers_from_server(self, server: Dict[str, Any]) -> Dict[str, str]:
416416
if not headers and "config" in server:
417417
headers = server["config"].get("headers", {})
418418

419+
# Normalize all header names to lowercase per RFC 7230
420+
headers = {k.lower(): v for k, v in headers.items()}
421+
419422
# Always add MCP Protocol Version header for HTTP connections
420423
server_type = server.get("type", "script")
421424
if server_type in ["sse", "streamable_http"]:
422-
headers["MCP-Protocol-Version"] = MCP_PROTOCOL_VERSION
425+
headers["mcp-protocol-version"] = MCP_PROTOCOL_VERSION
423426

424427
return headers
425428

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "mcp-client-for-ollama"
3-
version = "0.18.1"
3+
version = "0.18.2"
44
description = "MCP Client for Ollama - A client for connecting to Model Context Protocol servers using Ollama"
55
readme = "README.md"
66
requires-python = ">=3.10"

scripts/bump_version.py

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ def regenerate_uvlock(directory):
2525
def check_version_consistency(files):
2626
"""Check if versions are consistent across all files."""
2727
versions = {}
28-
29-
28+
29+
3030
# Check pyproject.toml files
3131
for name, file_path in files.items():
3232
if "pyproject" in name and file_path.exists():
3333
try:
3434
versions[str(file_path)] = read_version(file_path)
3535
except ValueError:
3636
versions[str(file_path)] = "VERSION NOT FOUND"
37-
37+
3838
# Check __init__.py files
3939
for name, file_path in files.items():
4040
if "init" in name and file_path.exists():
@@ -48,18 +48,18 @@ def check_version_consistency(files):
4848
versions[str(file_path)] = "VERSION NOT FOUND"
4949
except Exception:
5050
versions[str(file_path)] = "ERROR READING FILE"
51-
51+
5252
# Check if all versions match
53-
unique_versions = set(v for v in versions.values()
53+
unique_versions = set(v for v in versions.values()
5454
if v not in ["VERSION NOT FOUND", "ERROR READING FILE"])
55-
55+
5656
return unique_versions, versions
5757

5858
def read_version(file_path):
5959
"""Read the current version from a pyproject.toml file."""
6060
with open(file_path, 'r') as f:
6161
content = f.read()
62-
62+
6363
# Use regex to find the version line
6464
match = re.search(r'version\s*=\s*"([^"]+)"', content)
6565
if match:
@@ -71,7 +71,7 @@ def read_version(file_path):
7171
def bump_version(version, bump_type):
7272
"""Bump a version number based on semantic versioning."""
7373
major, minor, patch = map(int, version.split('.'))
74-
74+
7575
if bump_type == 'major':
7676
major += 1
7777
minor = 0
@@ -81,23 +81,23 @@ def bump_version(version, bump_type):
8181
patch = 0
8282
else: # patch
8383
patch += 1
84-
84+
8585
return f"{major}.{minor}.{patch}"
8686

8787

8888
def update_version_in_file(file_path, new_version):
8989
"""Update the version in a pyproject.toml file."""
9090
with open(file_path, 'r') as f:
9191
content = f.read()
92-
92+
9393
# Replace version in the version line - using a lambda for safe replacement
9494
version_pattern = re.compile(r'(version\s*=\s*)"([^"]+)"')
9595
updated_content = version_pattern.sub(lambda m: f'{m.group(1)}"{new_version}"', content)
96-
96+
9797
# Also update any dependency on the main package (for the CLI package)
9898
dep_pattern = re.compile(r'("mcp-client-for-ollama==)([^"]+)"')
9999
updated_content = dep_pattern.sub(lambda m: f'{m.group(1)}{new_version}"', updated_content)
100-
100+
101101
with open(file_path, 'w') as f:
102102
f.write(updated_content)
103103

@@ -107,41 +107,41 @@ def update_version_in_init(init_path, new_version):
107107
if os.path.exists(init_path):
108108
with open(init_path, 'r') as f:
109109
content = f.read()
110-
110+
111111
# Replace version in __version__ = "x.y.z" - using lambda for safe replacement
112112
version_pattern = re.compile(r'(__version__\s*=\s*)"([^"]+)"')
113113
updated_content = version_pattern.sub(lambda m: f'{m.group(1)}"{new_version}"', content)
114-
114+
115115
with open(init_path, 'w') as f:
116116
f.write(updated_content)
117117

118118

119119
def main():
120120
parser = argparse.ArgumentParser(description="Bump version for MCP Client for Ollama packages")
121121
parser.add_argument(
122-
"bump_type",
122+
"bump_type",
123123
choices=["patch", "minor", "major", "custom"],
124124
help="The type of version bump to perform following semantic versioning, or 'custom' to specify a specific version"
125125
)
126126
parser.add_argument(
127-
"--dry-run",
127+
"--dry-run",
128128
action="store_true",
129129
help="Show what would be done without making changes"
130130
)
131131
parser.add_argument(
132-
"--version",
132+
"--version",
133133
help="Custom version to set when using the 'custom' bump type"
134134
)
135135
parser.add_argument(
136-
"--force",
136+
"--force",
137137
action="store_true",
138138
help="Force version bump even if inconsistencies are detected"
139139
)
140140
args = parser.parse_args()
141-
141+
142142
# Get repo root directory
143-
repo_root = Path(__file__).parent.parent.absolute()
144-
143+
repo_root = Path(__file__).parent.parent.absolute()
144+
145145
# Define paths
146146
files = {
147147
"main_pyproject": repo_root / "pyproject.toml",
@@ -153,28 +153,28 @@ def main():
153153
# Calculate and check versions for consistency
154154
print("Checking version consistency across files...")
155155
unique_versions, all_versions = check_version_consistency(files)
156-
156+
157157
if len(unique_versions) > 1:
158158
print("\nWARNING: Version inconsistency detected!")
159159
print("The following files have different versions:")
160160
for file_path, version in all_versions.items():
161161
print(f" - {file_path}: {version}")
162-
162+
163163
if not args.force:
164164
print("\nOperation aborted. Use --force to proceed with version bump despite inconsistencies.")
165165
return
166166
print("\nProceeding with version bump despite inconsistencies (--force flag used).")
167167
else:
168-
print("\nAll files have consistent versions.")
168+
print("\nAll files have consistent versions.")
169169

170170
# Read current version from main package
171171
main_pyproject = repo_root / "pyproject.toml"
172172

173-
173+
174174
# Read current version
175175
current_version = read_version(main_pyproject)
176176
print(f"Current version: {current_version}")
177-
177+
178178
# Calculate new version
179179
if args.bump_type == "custom":
180180
if not args.version:
@@ -185,20 +185,20 @@ def main():
185185
parser.error(f"Invalid version format: {new_version}. Expected format: X.Y.Z")
186186
else:
187187
new_version = bump_version(current_version, args.bump_type)
188-
188+
189189
print(f"New version: {new_version}")
190-
190+
191191
if args.dry_run:
192192
print("Dry run - no changes made.")
193193
return
194-
194+
195195
# Update versions
196196
print(f"Updating main package version in {main_pyproject}")
197197
update_version_in_file(main_pyproject, new_version)
198-
198+
199199
print(f"Updating CLI package version in {files['cli_pyproject']}")
200200
update_version_in_file(files['cli_pyproject'], new_version)
201-
201+
202202
# Update __version__ in __init__.py files if they exist
203203
print(f"Checking for __init__.py files...")
204204
update_version_in_init(files['main_init'], new_version)
@@ -207,10 +207,12 @@ def main():
207207
# Regenerate uv.lock files
208208
print("Regenerating uv.lock files...")
209209
regenerate_uvlock(repo_root)
210-
210+
211211
print(f"Version bump complete! {current_version} -> {new_version}")
212212
print("\nNext steps:")
213-
print(f"1. Commit the changes: git commit -am \"Bump version to {new_version}\"")
213+
print("1. Commit the changes:")
214+
print(" git add -A")
215+
print(f" git commit -m 'chore(release): bump version to {new_version}'")
214216
print(f"2. Create a tag: git tag -a v{new_version} -m \"Version {new_version}\"")
215217
print("3. Push changes: git push && git push --tags")
216218
print("4. Build and publish the packages will be done automatically by CI/CD pipeline.")

0 commit comments

Comments
 (0)