From ff829f7826ce3040891b5a18cceca358c9ea5a0c Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sat, 30 Nov 2024 19:30:04 -0600 Subject: [PATCH 1/5] surge example --- examples/text_me.py | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 examples/text_me.py diff --git a/examples/text_me.py b/examples/text_me.py new file mode 100644 index 000000000..ea5eacc1f --- /dev/null +++ b/examples/text_me.py @@ -0,0 +1,48 @@ +# /// script +# dependencies = ["fastmcp"] + +""" +FastMCP Echo Server +""" + +import httpx +from pydantic_settings import BaseSettings, SettingsConfigDict + +from fastmcp import FastMCP + + +class SurgeSettings(BaseSettings): + model_config: SettingsConfigDict = SettingsConfigDict( + env_prefix="SURGE_", env_file=".env" + ) + + api_key: str + account_id: str + my_phone_number: str + + +# Create server +mcp = FastMCP("Text Me") +surge_settings = SurgeSettings() # type: ignore + + +@mcp.tool() +def text_me(text_content: str) -> str: + """Send a text message to a phone number""" + with httpx.Client() as client: + response = client.post( + "https://api.surgemsg.com/messages", + headers={ + "Authorization": surge_settings.api_key, + "Surge-Account": surge_settings.account_id, + "Content-Type": "application/json", + }, + json={ + "body": text_content, + "conversation": { + "contact": {"phone_number": surge_settings.my_phone_number} + }, + }, + ) + response.raise_for_status() + return response.json() From 1b2c9cbc676ba37ea7751635bf45b2a01a7c5df8 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sat, 30 Nov 2024 19:48:08 -0600 Subject: [PATCH 2/5] update example --- .gitignore | 1 + examples/text_me.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7cab6898b..5b78feb81 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ wheels/ # Virtual environments .venv .DS_Store +.env src/fastmcp/_version.py diff --git a/examples/text_me.py b/examples/text_me.py index ea5eacc1f..5750c05d3 100644 --- a/examples/text_me.py +++ b/examples/text_me.py @@ -19,6 +19,8 @@ class SurgeSettings(BaseSettings): api_key: str account_id: str my_phone_number: str + my_first_name: str + my_last_name: str # Create server @@ -26,21 +28,28 @@ mcp = FastMCP("Text Me") surge_settings = SurgeSettings() # type: ignore -@mcp.tool() +@mcp.tool( + name="text_me", + description="Send a text message to the number set as SURGE_MY_PHONE_NUMBER in the .env file", +) def text_me(text_content: str) -> str: """Send a text message to a phone number""" with httpx.Client() as client: response = client.post( "https://api.surgemsg.com/messages", headers={ - "Authorization": surge_settings.api_key, + "Authorization": f"Bearer {surge_settings.api_key}", "Surge-Account": surge_settings.account_id, "Content-Type": "application/json", }, json={ "body": text_content, "conversation": { - "contact": {"phone_number": surge_settings.my_phone_number} + "contact": { + "first_name": surge_settings.my_first_name, + "last_name": surge_settings.my_last_name, + "phone_number": surge_settings.my_phone_number, + } }, }, ) From c6e8de95b9243117503445fc25fb7ce98f69e3c0 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sat, 30 Nov 2024 20:50:43 -0600 Subject: [PATCH 3/5] more wip link em --- examples/text_me.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/text_me.py b/examples/text_me.py index 5750c05d3..dea488f71 100644 --- a/examples/text_me.py +++ b/examples/text_me.py @@ -1,11 +1,14 @@ # /// script # dependencies = ["fastmcp"] +# /// """ FastMCP Echo Server """ +from typing import Annotated import httpx +from pydantic import BeforeValidator from pydantic_settings import BaseSettings, SettingsConfigDict from fastmcp import FastMCP @@ -18,22 +21,21 @@ class SurgeSettings(BaseSettings): api_key: str account_id: str - my_phone_number: str + my_phone_number: Annotated[ + str, BeforeValidator(lambda v: "+" + v if not v.startswith("+") else v) + ] my_first_name: str my_last_name: str # Create server -mcp = FastMCP("Text Me") +mcp = FastMCP("Text me") surge_settings = SurgeSettings() # type: ignore -@mcp.tool( - name="text_me", - description="Send a text message to the number set as SURGE_MY_PHONE_NUMBER in the .env file", -) +@mcp.tool(name="textme", description="Send a text message to me") def text_me(text_content: str) -> str: - """Send a text message to a phone number""" + """Send a text message to a phone number via https://surgemsg.com/""" with httpx.Client() as client: response = client.post( "https://api.surgemsg.com/messages", @@ -54,4 +56,4 @@ def text_me(text_content: str) -> str: }, ) response.raise_for_status() - return response.json() + return f"Message sent: {text_content}" From 2cc06fe6397ba64faa626aa9c66319749fc16a25 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sat, 30 Nov 2024 21:47:40 -0600 Subject: [PATCH 4/5] only test on changes to src/* doh --- .github/workflows/run-tests.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 848c63272..452fc63d1 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -7,7 +7,18 @@ env: on: push: branches: ["main"] + paths: + - "src/**" + - "tests/**" + - "uv.lock" + - "pyproject.toml" pull_request: + paths: + - "src/**" + - "tests/**" + - "uv.lock" + - "pyproject.toml" + workflow_dispatch: permissions: From cbb8dbeccfa62479900d12f38cff6267cea61249 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sat, 30 Nov 2024 22:16:21 -0600 Subject: [PATCH 5/5] add module docstring --- examples/text_me.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/text_me.py b/examples/text_me.py index dea488f71..d81c34a2a 100644 --- a/examples/text_me.py +++ b/examples/text_me.py @@ -3,7 +3,19 @@ # /// """ -FastMCP Echo Server +FastMCP Text Me Server +-------------------------------- +This defines a simple FastMCP server that sends a text message to a phone number via https://surgemsg.com/. + +To run this example, create a `.env` file with the following values: + +SURGE_API_KEY=... +SURGE_ACCOUNT_ID=... +SURGE_MY_PHONE_NUMBER=... +SURGE_MY_FIRST_NAME=... +SURGE_MY_LAST_NAME=... + +Visit https://surgemsg.com/ and click "Get Started" to obtain these values. """ from typing import Annotated