Skip to content

Commit 5439619

Browse files
authored
Use 120 characters instead of 88 (#856)
1 parent f7265f7 commit 5439619

File tree

90 files changed

+687
-2142
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+687
-2142
lines changed

examples/fastmcp/memory.py

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,14 @@
4747

4848
DB_DSN = "postgresql://postgres:postgres@localhost:54320/memory_db"
4949
# reset memory with rm ~/.fastmcp/{USER}/memory/*
50-
PROFILE_DIR = (
51-
Path.home() / ".fastmcp" / os.environ.get("USER", "anon") / "memory"
52-
).resolve()
50+
PROFILE_DIR = (Path.home() / ".fastmcp" / os.environ.get("USER", "anon") / "memory").resolve()
5351
PROFILE_DIR.mkdir(parents=True, exist_ok=True)
5452

5553

5654
def cosine_similarity(a: list[float], b: list[float]) -> float:
5755
a_array = np.array(a, dtype=np.float64)
5856
b_array = np.array(b, dtype=np.float64)
59-
return np.dot(a_array, b_array) / (
60-
np.linalg.norm(a_array) * np.linalg.norm(b_array)
61-
)
57+
return np.dot(a_array, b_array) / (np.linalg.norm(a_array) * np.linalg.norm(b_array))
6258

6359

6460
async def do_ai[T](
@@ -97,9 +93,7 @@ class MemoryNode(BaseModel):
9793
summary: str = ""
9894
importance: float = 1.0
9995
access_count: int = 0
100-
timestamp: float = Field(
101-
default_factory=lambda: datetime.now(timezone.utc).timestamp()
102-
)
96+
timestamp: float = Field(default_factory=lambda: datetime.now(timezone.utc).timestamp())
10397
embedding: list[float]
10498

10599
@classmethod
@@ -152,9 +146,7 @@ async def merge_with(self, other: Self, deps: Deps):
152146
self.importance += other.importance
153147
self.access_count += other.access_count
154148
self.embedding = [(a + b) / 2 for a, b in zip(self.embedding, other.embedding)]
155-
self.summary = await do_ai(
156-
self.content, "Summarize the following text concisely.", str, deps
157-
)
149+
self.summary = await do_ai(self.content, "Summarize the following text concisely.", str, deps)
158150
await self.save(deps)
159151
# Delete the merged node from the database
160152
if other.id is not None:
@@ -221,9 +213,7 @@ async def find_similar_memories(embedding: list[float], deps: Deps) -> list[Memo
221213

222214
async def update_importance(user_embedding: list[float], deps: Deps):
223215
async with deps.pool.acquire() as conn:
224-
rows = await conn.fetch(
225-
"SELECT id, importance, access_count, embedding FROM memories"
226-
)
216+
rows = await conn.fetch("SELECT id, importance, access_count, embedding FROM memories")
227217
for row in rows:
228218
memory_embedding = row["embedding"]
229219
similarity = cosine_similarity(user_embedding, memory_embedding)
@@ -273,25 +263,19 @@ async def display_memory_tree(deps: Deps) -> str:
273263
)
274264
result = ""
275265
for row in rows:
276-
effective_importance = row["importance"] * (
277-
1 + math.log(row["access_count"] + 1)
278-
)
266+
effective_importance = row["importance"] * (1 + math.log(row["access_count"] + 1))
279267
summary = row["summary"] or row["content"]
280268
result += f"- {summary} (Importance: {effective_importance:.2f})\n"
281269
return result
282270

283271

284272
@mcp.tool()
285273
async def remember(
286-
contents: list[str] = Field(
287-
description="List of observations or memories to store"
288-
),
274+
contents: list[str] = Field(description="List of observations or memories to store"),
289275
):
290276
deps = Deps(openai=AsyncOpenAI(), pool=await get_db_pool())
291277
try:
292-
return "\n".join(
293-
await asyncio.gather(*[add_memory(content, deps) for content in contents])
294-
)
278+
return "\n".join(await asyncio.gather(*[add_memory(content, deps) for content in contents]))
295279
finally:
296280
await deps.pool.close()
297281

@@ -305,9 +289,7 @@ async def read_profile() -> str:
305289

306290

307291
async def initialize_database():
308-
pool = await asyncpg.create_pool(
309-
"postgresql://postgres:postgres@localhost:54320/postgres"
310-
)
292+
pool = await asyncpg.create_pool("postgresql://postgres:postgres@localhost:54320/postgres")
311293
try:
312294
async with pool.acquire() as conn:
313295
await conn.execute("""

examples/fastmcp/text_me.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,11 @@
2828

2929

3030
class SurgeSettings(BaseSettings):
31-
model_config: SettingsConfigDict = SettingsConfigDict(
32-
env_prefix="SURGE_", env_file=".env"
33-
)
31+
model_config: SettingsConfigDict = SettingsConfigDict(env_prefix="SURGE_", env_file=".env")
3432

3533
api_key: str
3634
account_id: str
37-
my_phone_number: Annotated[
38-
str, BeforeValidator(lambda v: "+" + v if not v.startswith("+") else v)
39-
]
35+
my_phone_number: Annotated[str, BeforeValidator(lambda v: "+" + v if not v.startswith("+") else v)]
4036
my_first_name: str
4137
my_last_name: str
4238

examples/fastmcp/unicode_example.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88
mcp = FastMCP()
99

1010

11-
@mcp.tool(
12-
description="🌟 A tool that uses various Unicode characters in its description: "
13-
"á é í ó ú ñ 漢字 🎉"
14-
)
11+
@mcp.tool(description="🌟 A tool that uses various Unicode characters in its description: " "á é í ó ú ñ 漢字 🎉")
1512
def hello_unicode(name: str = "世界", greeting: str = "¡Hola") -> str:
1613
"""
1714
A simple tool that demonstrates Unicode handling in:

examples/servers/simple-auth/mcp_simple_auth/server.py

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,15 @@ async def register_client(self, client_info: OAuthClientInformationFull):
8282
"""Register a new OAuth client."""
8383
self.clients[client_info.client_id] = client_info
8484

85-
async def authorize(
86-
self, client: OAuthClientInformationFull, params: AuthorizationParams
87-
) -> str:
85+
async def authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str:
8886
"""Generate an authorization URL for GitHub OAuth flow."""
8987
state = params.state or secrets.token_hex(16)
9088

9189
# Store the state mapping
9290
self.state_mapping[state] = {
9391
"redirect_uri": str(params.redirect_uri),
9492
"code_challenge": params.code_challenge,
95-
"redirect_uri_provided_explicitly": str(
96-
params.redirect_uri_provided_explicitly
97-
),
93+
"redirect_uri_provided_explicitly": str(params.redirect_uri_provided_explicitly),
9894
"client_id": client.client_id,
9995
}
10096

@@ -117,9 +113,7 @@ async def handle_github_callback(self, code: str, state: str) -> str:
117113

118114
redirect_uri = state_data["redirect_uri"]
119115
code_challenge = state_data["code_challenge"]
120-
redirect_uri_provided_explicitly = (
121-
state_data["redirect_uri_provided_explicitly"] == "True"
122-
)
116+
redirect_uri_provided_explicitly = state_data["redirect_uri_provided_explicitly"] == "True"
123117
client_id = state_data["client_id"]
124118

125119
# Exchange code for token with GitHub
@@ -200,8 +194,7 @@ async def exchange_authorization_code(
200194
for token, data in self.tokens.items()
201195
# see https://github.blog/engineering/platform-security/behind-githubs-new-authentication-token-formats/
202196
# which you get depends on your GH app setup.
203-
if (token.startswith("ghu_") or token.startswith("gho_"))
204-
and data.client_id == client.client_id
197+
if (token.startswith("ghu_") or token.startswith("gho_")) and data.client_id == client.client_id
205198
),
206199
None,
207200
)
@@ -232,9 +225,7 @@ async def load_access_token(self, token: str) -> AccessToken | None:
232225

233226
return access_token
234227

235-
async def load_refresh_token(
236-
self, client: OAuthClientInformationFull, refresh_token: str
237-
) -> RefreshToken | None:
228+
async def load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None:
238229
"""Load a refresh token - not supported."""
239230
return None
240231

@@ -247,9 +238,7 @@ async def exchange_refresh_token(
247238
"""Exchange refresh token"""
248239
raise NotImplementedError("Not supported")
249240

250-
async def revoke_token(
251-
self, token: str, token_type_hint: str | None = None
252-
) -> None:
241+
async def revoke_token(self, token: str, token_type_hint: str | None = None) -> None:
253242
"""Revoke a token."""
254243
if token in self.tokens:
255244
del self.tokens[token]
@@ -335,9 +324,7 @@ async def get_user_profile() -> dict[str, Any]:
335324
)
336325

337326
if response.status_code != 200:
338-
raise ValueError(
339-
f"GitHub API error: {response.status_code} - {response.text}"
340-
)
327+
raise ValueError(f"GitHub API error: {response.status_code} - {response.text}")
341328

342329
return response.json()
343330

@@ -361,9 +348,7 @@ def main(port: int, host: str, transport: Literal["sse", "streamable-http"]) ->
361348
# No hardcoded credentials - all from environment variables
362349
settings = ServerSettings(host=host, port=port)
363350
except ValueError as e:
364-
logger.error(
365-
"Failed to load settings. Make sure environment variables are set:"
366-
)
351+
logger.error("Failed to load settings. Make sure environment variables are set:")
367352
logger.error(" MCP_GITHUB_GITHUB_CLIENT_ID=<your-client-id>")
368353
logger.error(" MCP_GITHUB_GITHUB_CLIENT_SECRET=<your-client-secret>")
369354
logger.error(f"Error: {e}")

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ select = ["C4", "E", "F", "I", "PERF", "UP"]
9696
ignore = ["PERF203"]
9797

9898
[tool.ruff]
99-
line-length = 88
99+
line-length = 120
100100
target-version = "py310"
101101

102102
[tool.ruff.lint.per-file-ignores]

src/mcp/cli/claude.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ def get_claude_config_path() -> Path | None:
2121
elif sys.platform == "darwin":
2222
path = Path(Path.home(), "Library", "Application Support", "Claude")
2323
elif sys.platform.startswith("linux"):
24-
path = Path(
25-
os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"), "Claude"
26-
)
24+
path = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"), "Claude")
2725
else:
2826
return None
2927

@@ -37,8 +35,7 @@ def get_uv_path() -> str:
3735
uv_path = shutil.which("uv")
3836
if not uv_path:
3937
logger.error(
40-
"uv executable not found in PATH, falling back to 'uv'. "
41-
"Please ensure uv is installed and in your PATH"
38+
"uv executable not found in PATH, falling back to 'uv'. " "Please ensure uv is installed and in your PATH"
4239
)
4340
return "uv" # Fall back to just "uv" if not found
4441
return uv_path
@@ -94,10 +91,7 @@ def update_claude_config(
9491
config["mcpServers"] = {}
9592

9693
# Always preserve existing env vars and merge with new ones
97-
if (
98-
server_name in config["mcpServers"]
99-
and "env" in config["mcpServers"][server_name]
100-
):
94+
if server_name in config["mcpServers"] and "env" in config["mcpServers"][server_name]:
10195
existing_env = config["mcpServers"][server_name]["env"]
10296
if env_vars:
10397
# New vars take precedence over existing ones

src/mcp/cli/cli.py

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ def _get_npx_command():
4545
# Try both npx.cmd and npx.exe on Windows
4646
for cmd in ["npx.cmd", "npx.exe", "npx"]:
4747
try:
48-
subprocess.run(
49-
[cmd, "--version"], check=True, capture_output=True, shell=True
50-
)
48+
subprocess.run([cmd, "--version"], check=True, capture_output=True, shell=True)
5149
return cmd
5250
except subprocess.CalledProcessError:
5351
continue
@@ -58,9 +56,7 @@ def _get_npx_command():
5856
def _parse_env_var(env_var: str) -> tuple[str, str]:
5957
"""Parse environment variable string in format KEY=VALUE."""
6058
if "=" not in env_var:
61-
logger.error(
62-
f"Invalid environment variable format: {env_var}. Must be KEY=VALUE"
63-
)
59+
logger.error(f"Invalid environment variable format: {env_var}. Must be KEY=VALUE")
6460
sys.exit(1)
6561
key, value = env_var.split("=", 1)
6662
return key.strip(), value.strip()
@@ -154,14 +150,10 @@ def _check_server_object(server_object: Any, object_name: str):
154150
True if it's supported.
155151
"""
156152
if not isinstance(server_object, FastMCP):
157-
logger.error(
158-
f"The server object {object_name} is of type "
159-
f"{type(server_object)} (expecting {FastMCP})."
160-
)
153+
logger.error(f"The server object {object_name} is of type " f"{type(server_object)} (expecting {FastMCP}).")
161154
if isinstance(server_object, LowLevelServer):
162155
logger.warning(
163-
"Note that only FastMCP server is supported. Low level "
164-
"Server class is not yet supported."
156+
"Note that only FastMCP server is supported. Low level " "Server class is not yet supported."
165157
)
166158
return False
167159
return True
@@ -172,10 +164,7 @@ def _check_server_object(server_object: Any, object_name: str):
172164
for name in ["mcp", "server", "app"]:
173165
if hasattr(module, name):
174166
if not _check_server_object(getattr(module, name), f"{file}:{name}"):
175-
logger.error(
176-
f"Ignoring object '{file}:{name}' as it's not a valid "
177-
"server object"
178-
)
167+
logger.error(f"Ignoring object '{file}:{name}' as it's not a valid " "server object")
179168
continue
180169
return getattr(module, name)
181170

@@ -280,8 +269,7 @@ def dev(
280269
npx_cmd = _get_npx_command()
281270
if not npx_cmd:
282271
logger.error(
283-
"npx not found. Please ensure Node.js and npm are properly installed "
284-
"and added to your system PATH."
272+
"npx not found. Please ensure Node.js and npm are properly installed " "and added to your system PATH."
285273
)
286274
sys.exit(1)
287275

@@ -383,8 +371,7 @@ def install(
383371
typer.Option(
384372
"--name",
385373
"-n",
386-
help="Custom name for the server (defaults to server's name attribute or"
387-
" file name)",
374+
help="Custom name for the server (defaults to server's name attribute or" " file name)",
388375
),
389376
] = None,
390377
with_editable: Annotated[
@@ -458,8 +445,7 @@ def install(
458445
name = server.name
459446
except (ImportError, ModuleNotFoundError) as e:
460447
logger.debug(
461-
"Could not import server (likely missing dependencies), using file"
462-
" name",
448+
"Could not import server (likely missing dependencies), using file" " name",
463449
extra={"error": str(e)},
464450
)
465451
name = file.stem
@@ -477,11 +463,7 @@ def install(
477463
if env_file:
478464
if dotenv:
479465
try:
480-
env_dict |= {
481-
k: v
482-
for k, v in dotenv.dotenv_values(env_file).items()
483-
if v is not None
484-
}
466+
env_dict |= {k: v for k, v in dotenv.dotenv_values(env_file).items() if v is not None}
485467
except Exception as e:
486468
logger.error(f"Failed to load .env file: {e}")
487469
sys.exit(1)

src/mcp/client/__main__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424

2525

2626
async def message_handler(
27-
message: RequestResponder[types.ServerRequest, types.ClientResult]
28-
| types.ServerNotification
29-
| Exception,
27+
message: RequestResponder[types.ServerRequest, types.ClientResult] | types.ServerNotification | Exception,
3028
) -> None:
3129
if isinstance(message, Exception):
3230
logger.error("Error: %s", message)
@@ -60,9 +58,7 @@ async def main(command_or_url: str, args: list[str], env: list[tuple[str, str]])
6058
await run_session(*streams)
6159
else:
6260
# Use stdio client for commands
63-
server_parameters = StdioServerParameters(
64-
command=command_or_url, args=args, env=env_dict
65-
)
61+
server_parameters = StdioServerParameters(command=command_or_url, args=args, env=env_dict)
6662
async with stdio_client(server_parameters) as streams:
6763
await run_session(*streams)
6864

0 commit comments

Comments
 (0)