forked from infinitimeless/LMStudio-MCP
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlmstudio_bridge.py
More file actions
157 lines (127 loc) · 5.14 KB
/
Copy pathlmstudio_bridge.py
File metadata and controls
157 lines (127 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env python3
from mcp.server.fastmcp import FastMCP
import requests
import json
import sys
from typing import List, Dict, Any, Optional
# Initialize FastMCP server
mcp = FastMCP("lmstudio-bridge")
# LM Studio settings
LMSTUDIO_API_BASE = "http://127.0.0.1:1234"
DEFAULT_MODEL = "default" # Will be replaced with whatever model is currently loaded
def log_error(message: str):
"""Log error messages to stderr for debugging"""
print(f"ERROR: {message}", file=sys.stderr)
def log_info(message: str):
"""Log informational messages to stderr for debugging"""
print(f"INFO: {message}", file=sys.stderr)
@mcp.tool()
async def health_check() -> str:
"""Check if LM Studio API is accessible.
Returns:
A message indicating whether the LM Studio API is running.
"""
try:
response = requests.get(f"{LMSTUDIO_API_BASE}/v1/models")
if response.status_code == 200:
return "LM Studio API is running and accessible."
else:
return f"LM Studio API returned status code {response.status_code}."
except Exception as e:
return f"Error connecting to LM Studio API: {str(e)}"
@mcp.tool()
async def list_models() -> str:
"""List all available models in LM Studio.
Returns:
A formatted list of available models.
"""
try:
response = requests.get(f"{LMSTUDIO_API_BASE}/v1/models")
if response.status_code != 200:
return f"Failed to fetch models. Status code: {response.status_code}"
models = response.json().get("data", [])
if not models:
return "No models found in LM Studio."
result = "Available models in LM Studio:\n\n"
for model in models:
result += f"- {model['id']}\n"
return result
except Exception as e:
log_error(f"Error in list_models: {str(e)}")
return f"Error listing models: {str(e)}"
@mcp.tool()
async def get_current_model() -> str:
"""Get the currently loaded model in LM Studio.
Returns:
The name of the currently loaded model.
"""
try:
# LM Studio doesn't have a direct endpoint for currently loaded model
# We'll check which model responds to a simple completion request
response = requests.post(
f"{LMSTUDIO_API_BASE}/v1/chat/completions",
json={
"messages": [{"role": "system", "content": "What model are you?"}],
"temperature": 0.7,
"max_tokens": 10
}
)
if response.status_code != 200:
return f"Failed to identify current model. Status code: {response.status_code}"
# Extract model info from response
model_info = response.json().get("model", "Unknown")
return f"Currently loaded model: {model_info}"
except Exception as e:
log_error(f"Error in get_current_model: {str(e)}")
return f"Error identifying current model: {str(e)}"
@mcp.tool()
async def chat_completion(prompt: str, system_prompt: str = "", temperature: float = 0.7, max_tokens: int = 1024) -> str:
"""Generate a completion from the current LM Studio model.
Args:
prompt: The user's prompt to send to the model
system_prompt: Optional system instructions for the model
temperature: Controls randomness (0.0 to 1.0)
max_tokens: Maximum number of tokens to generate
Returns:
The model's response to the prompt
"""
try:
messages = []
# Add system message if provided
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
# Add user message
messages.append({"role": "user", "content": prompt})
log_info(f"Sending request to LM Studio with {len(messages)} messages")
response = requests.post(
f"{LMSTUDIO_API_BASE}/v1/chat/completions",
json={
"messages": messages,
"temperature": temperature,
"max_tokens": max_tokens
}
)
if response.status_code != 200:
log_error(f"LM Studio API error: {response.status_code}")
return f"Error: LM Studio returned status code {response.status_code}"
response_json = response.json()
log_info(f"Received response from LM Studio")
# Extract the assistant's message
choices = response_json.get("choices", [])
if not choices:
return "Error: No response generated"
message = choices[0].get("message", {})
content = message.get("content", "")
if not content:
return "Error: Empty response from model"
return content
except Exception as e:
log_error(f"Error in chat_completion: {str(e)}")
return f"Error generating completion: {str(e)}"
def main():
"""Entry point for the package when installed via pip"""
log_info("Starting LM Studio Bridge MCP Server")
mcp.run(transport='stdio')
if __name__ == "__main__":
# Initialize and run the server
main()