Use 120 characters instead of 88 (#856)

This commit is contained in:
Marcelo Trylesinski 2025-06-11 02:45:50 -07:00 • committed by GitHub
commit 543961968c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 687 additions and 2142 deletions

View file

@ -47,18 +47,14 @@ mcp = FastMCP(
DB_DSN = "postgresql://postgres:postgres@localhost:54320/memory_db"
# reset memory with rm ~/.fastmcp/{USER}/memory/*
PROFILE_DIR = (
Path.home() / ".fastmcp" / os.environ.get("USER", "anon") / "memory"
).resolve()
PROFILE_DIR = (Path.home() / ".fastmcp" / os.environ.get("USER", "anon") / "memory").resolve()
PROFILE_DIR.mkdir(parents=True, exist_ok=True)
def cosine_similarity(a: list[float], b: list[float]) -> float:
a_array = np.array(a, dtype=np.float64)
b_array = np.array(b, dtype=np.float64)
return np.dot(a_array, b_array) / (
np.linalg.norm(a_array) * np.linalg.norm(b_array)
)
return np.dot(a_array, b_array) / (np.linalg.norm(a_array) * np.linalg.norm(b_array))
async def do_ai[T](
@ -97,9 +93,7 @@ class MemoryNode(BaseModel):
summary: str = ""
importance: float = 1.0
access_count: int = 0
timestamp: float = Field(
default_factory=lambda: datetime.now(timezone.utc).timestamp()
)
timestamp: float = Field(default_factory=lambda: datetime.now(timezone.utc).timestamp())
embedding: list[float]
@classmethod
@ -152,9 +146,7 @@ class MemoryNode(BaseModel):
self.importance += other.importance
self.access_count += other.access_count
self.embedding = [(a + b) / 2 for a, b in zip(self.embedding, other.embedding)]
self.summary = await do_ai(
self.content, "Summarize the following text concisely.", str, deps
)
self.summary = await do_ai(self.content, "Summarize the following text concisely.", str, deps)
await self.save(deps)
# Delete the merged node from the database
if other.id is not None:
@ -221,9 +213,7 @@ async def find_similar_memories(embedding: list[float], deps: Deps) -> list[Memo
async def update_importance(user_embedding: list[float], deps: Deps):
async with deps.pool.acquire() as conn:
rows = await conn.fetch(
"SELECT id, importance, access_count, embedding FROM memories"
)
rows = await conn.fetch("SELECT id, importance, access_count, embedding FROM memories")
for row in rows:
memory_embedding = row["embedding"]
similarity = cosine_similarity(user_embedding, memory_embedding)
@ -273,9 +263,7 @@ async def display_memory_tree(deps: Deps) -> str:
)
result = ""
for row in rows:
effective_importance = row["importance"] * (
1 + math.log(row["access_count"] + 1)
)
effective_importance = row["importance"] * (1 + math.log(row["access_count"] + 1))
summary = row["summary"] or row["content"]
result += f"- {summary} (Importance: {effective_importance:.2f})\n"
return result
@ -283,15 +271,11 @@ async def display_memory_tree(deps: Deps) -> str:
@mcp.tool()
async def remember(
contents: list[str] = Field(
description="List of observations or memories to store"
),
contents: list[str] = Field(description="List of observations or memories to store"),
):
deps = Deps(openai=AsyncOpenAI(), pool=await get_db_pool())
try:
return "\n".join(
await asyncio.gather(*[add_memory(content, deps) for content in contents])
)
return "\n".join(await asyncio.gather(*[add_memory(content, deps) for content in contents]))
finally:
await deps.pool.close()
@ -305,9 +289,7 @@ async def read_profile() -> str:
async def initialize_database():
pool = await asyncpg.create_pool(
"postgresql://postgres:postgres@localhost:54320/postgres"
)
pool = await asyncpg.create_pool("postgresql://postgres:postgres@localhost:54320/postgres")
try:
async with pool.acquire() as conn:
await conn.execute("""

View file

@ -28,15 +28,11 @@ from mcp.server.fastmcp import FastMCP
class SurgeSettings(BaseSettings):
model_config: SettingsConfigDict = SettingsConfigDict(
env_prefix="SURGE_", env_file=".env"
)
model_config: SettingsConfigDict = SettingsConfigDict(env_prefix="SURGE_", env_file=".env")
api_key: str
account_id: str
my_phone_number: Annotated[
str, BeforeValidator(lambda v: "+" + v if not v.startswith("+") else v)
]
my_phone_number: Annotated[str, BeforeValidator(lambda v: "+" + v if not v.startswith("+") else v)]
my_first_name: str
my_last_name: str

View file

@ -8,10 +8,7 @@ from mcp.server.fastmcp import FastMCP
mcp = FastMCP()
@mcp.tool(
description="🌟 A tool that uses various Unicode characters in its description: "
"á é í ó ú ñ 漢字 🎉"
)
@mcp.tool(description="🌟 A tool that uses various Unicode characters in its description: " "á é í ó ú ñ 漢字 🎉")
def hello_unicode(name: str = "世界", greeting: str = "¡Hola") -> str:
"""
A simple tool that demonstrates Unicode handling in:

View file

@ -82,9 +82,7 @@ class SimpleGitHubOAuthProvider(OAuthAuthorizationServerProvider):
"""Register a new OAuth client."""
self.clients[client_info.client_id] = client_info
async def authorize(
self, client: OAuthClientInformationFull, params: AuthorizationParams
) -> str:
async def authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str:
"""Generate an authorization URL for GitHub OAuth flow."""
state = params.state or secrets.token_hex(16)
@ -92,9 +90,7 @@ class SimpleGitHubOAuthProvider(OAuthAuthorizationServerProvider):
self.state_mapping[state] = {
"redirect_uri": str(params.redirect_uri),
"code_challenge": params.code_challenge,
"redirect_uri_provided_explicitly": str(
params.redirect_uri_provided_explicitly
),
"redirect_uri_provided_explicitly": str(params.redirect_uri_provided_explicitly),
"client_id": client.client_id,
}
@ -117,9 +113,7 @@ class SimpleGitHubOAuthProvider(OAuthAuthorizationServerProvider):
redirect_uri = state_data["redirect_uri"]
code_challenge = state_data["code_challenge"]
redirect_uri_provided_explicitly = (
state_data["redirect_uri_provided_explicitly"] == "True"
)
redirect_uri_provided_explicitly = state_data["redirect_uri_provided_explicitly"] == "True"
client_id = state_data["client_id"]
# Exchange code for token with GitHub
@ -200,8 +194,7 @@ class SimpleGitHubOAuthProvider(OAuthAuthorizationServerProvider):
for token, data in self.tokens.items()
# see https://github.blog/engineering/platform-security/behind-githubs-new-authentication-token-formats/
# which you get depends on your GH app setup.
if (token.startswith("ghu_") or token.startswith("gho_"))
and data.client_id == client.client_id
if (token.startswith("ghu_") or token.startswith("gho_")) and data.client_id == client.client_id
),
None,
)
@ -232,9 +225,7 @@ class SimpleGitHubOAuthProvider(OAuthAuthorizationServerProvider):
return access_token
async def load_refresh_token(
self, client: OAuthClientInformationFull, refresh_token: str
) -> RefreshToken | None:
async def load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None:
"""Load a refresh token - not supported."""
return None
@ -247,9 +238,7 @@ class SimpleGitHubOAuthProvider(OAuthAuthorizationServerProvider):
"""Exchange refresh token"""
raise NotImplementedError("Not supported")
async def revoke_token(
self, token: str, token_type_hint: str | None = None
) -> None:
async def revoke_token(self, token: str, token_type_hint: str | None = None) -> None:
"""Revoke a token."""
if token in self.tokens:
del self.tokens[token]
@ -335,9 +324,7 @@ def create_simple_mcp_server(settings: ServerSettings) -> FastMCP:
)
if response.status_code != 200:
raise ValueError(
f"GitHub API error: {response.status_code} - {response.text}"
)
raise ValueError(f"GitHub API error: {response.status_code} - {response.text}")
return response.json()
@ -361,9 +348,7 @@ def main(port: int, host: str, transport: Literal["sse", "streamable-http"]) ->
# No hardcoded credentials - all from environment variables
settings = ServerSettings(host=host, port=port)
except ValueError as e:
logger.error(
"Failed to load settings. Make sure environment variables are set:"
)
logger.error("Failed to load settings. Make sure environment variables are set:")
logger.error(" MCP_GITHUB_GITHUB_CLIENT_ID=<your-client-id>")
logger.error(" MCP_GITHUB_GITHUB_CLIENT_SECRET=<your-client-secret>")
logger.error(f"Error: {e}")