### Create a Simple MCP Server with FastMCP Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md This example demonstrates how to create a basic MCP server using FastMCP, exposing an addition tool and a dynamic greeting resource. It shows the minimal boilerplate required to get started. ```python # server.py from fastmcp import FastMCP # Create an MCP server mcp = FastMCP("Demo") # Add an addition tool @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b # Add a dynamic greeting resource @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """Get a personalized greeting""" return f"Hello, {name}!" ``` -------------------------------- ### Windows Environment Setup with uv Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Sets up a Python virtual environment and installs FastMCP with development dependencies on Windows using 'uv'. ```bash uv venv .venv\Scripts\activate uv pip install -e ".[dev]" ``` -------------------------------- ### Install Dependencies with uv Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Install all required project dependencies listed in requirements.txt using uv. ```bash # Using uv: uv pip install -r requirements.txt ``` -------------------------------- ### Install uv Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md If uv is not installed, use pip to install it first, then create the virtual environment. ```bash # If uv is not installed, install it first: pip install uv ``` -------------------------------- ### Install Dependencies with pip Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Install all required project dependencies listed in requirements.txt using the standard pip. ```bash # OR using standard pip: pip install -r requirements.txt ``` -------------------------------- ### Install Demo MCP Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Command to install the demo MCP server. This makes the 'add' tool available to LLM applications. ```bash fastmcp install demo.py ``` -------------------------------- ### Install uv with python3 Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Install uv using the python3 module if you encounter 'pip not found' errors. ```bash # Or to install uv: python3 -m pip install uv ``` -------------------------------- ### Install FastMCP with uv Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Recommended installation command for FastMCP using uv, a fast Python package installer. This is required for deploying MCP servers. ```bash uv pip install fastmcp ``` -------------------------------- ### Test Installing with Environment Variables from File Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Tests installing a server using environment variables defined in a separate file. Verifies that variables from the file are correctly loaded and applied. ```python def test_install_with_env_file(mock_config, server_file, mock_env_file): """Test installing with environment variables from a file.""" runner = CliRunner() with patch("fastmcp.cli.claude.get_claude_config_path") as mock_config_path: mock_config_path.return_value = mock_config.parent result = runner.invoke( app, ["install", str(server_file), "--env-file", str(mock_env_file)], ) assert result.exit_code == 0 # Read the config file and check env vars config = json.loads(mock_config.read_text()) assert "mcpServers" in config assert len(config["mcpServers"]) == 1 server = next(iter(config["mcpServers"].values())) assert server["env"] == {"FOO": "bar", "BAZ": "123"} ``` -------------------------------- ### Copy .env.example to .env Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Create a .env file by copying the example configuration file. This file will store your environment-specific settings. ```bash cp .env.example .env ``` -------------------------------- ### Test Installing with Environment Variables Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Tests the installation of a server with environment variables provided directly or as a dictionary. Ensures that environment variables are correctly parsed and applied. ```python ( ["--env-var", "FOO=bar"], {"FOO": "bar"}, ), # Multiple env vars ( ["--env-var", "FOO=bar", "--env-var", "BAZ=123"], {"FOO": "bar", "BAZ": "123"}, ), # Env var with spaces ( ["--env-var", "FOO=bar baz"], {"FOO": "bar baz"}, ), ], ) def test_install_with_env_vars(mock_config, server_file, args, expected_env): """Test installing with environment variables.""" runner = CliRunner() with patch("fastmcp.cli.claude.get_claude_config_path") as mock_config_path: mock_config_path.return_value = mock_config.parent result = runner.invoke( app, ["install", str(server_file)] + args, ) assert result.exit_code == 0 # Read the config file and check env vars config = json.loads(mock_config.read_text()) assert "mcpServers" in config assert len(config["mcpServers"]) == 1 server = next(iter(config["mcpServers"].values())) assert server["env"] == expected_env ``` -------------------------------- ### Install FastMCP with Testing Dependencies Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Installs only the testing dependencies for FastMCP using 'uv'. Suitable for CI environments. ```bash uv sync --frozen --extra tests ``` -------------------------------- ### Install FastMCP with Development Dependencies Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Clones the FastMCP repository and installs development dependencies using 'uv'. Recommended for local development. ```bash git clone https://github.com/jlowin/fastmcp.git cd fastmcp uv sync --frozen --extra dev ``` -------------------------------- ### Test Server Dependencies Installation Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Tests the installation of a server with specified dependencies. Verifies that the dependencies are correctly added to the server's arguments in the configuration. ```python def test_server_dependencies(mock_config, server_file): """Test that server dependencies are correctly handled.""" # Create a server file with dependencies server_file = server_file.parent / "server_with_deps.py" server_file.write_text( """from fastmcp import FastMCP mcp = FastMCP("test", dependencies=["pandas", "numpy"]) """ ) runner = CliRunner() with patch("fastmcp.cli.claude.get_claude_config_path") as mock_config_path: mock_config_path.return_value = mock_config.parent result = runner.invoke(app, ["install", str(server_file)]) assert result.exit_code == 0 # Read the config file and check dependencies were added as --with args config = json.loads(mock_config.read_text()) server = next(iter(config["mcpServers"].values())) assert "--with" in server["args"] assert "pandas" in server["args"] assert "numpy" in server["args"] ``` -------------------------------- ### Run FastMCP Development Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Starts a development server for FastMCP, optionally installing additional packages in editable mode. It builds a uv command and executes the MCP Inspector using npx. Handles subprocess errors and FileNotFoundError if npx is not found. ```python file, server_object = _parse_file_path(file_spec) logger.debug( "Starting dev server", extra={ "file": str(file), "server_object": server_object, "with_editable": str(with_editable) if with_editable else None, "with_packages": with_packages, }, ) try: # Import server to get dependencies server = _import_server(file, server_object) if hasattr(server, "dependencies"): with_packages = list(set(with_packages + server.dependencies)) uv_cmd = _build_uv_command(file_spec, with_editable, with_packages) # Get the correct npx command npx_cmd = _get_npx_command() if not npx_cmd: logger.error( "npx not found. Please ensure Node.js and npm are properly installed " "and added to your system PATH." ) sys.exit(1) # Run the MCP Inspector command with shell=True on Windows shell = sys.platform == "win32" process = subprocess.run( [npx_cmd, "@modelcontextprotocol/inspector"] + uv_cmd, check=True, shell=shell, env=dict(os.environ.items()), # Convert to list of tuples for env update ) sys.exit(process.returncode) except subprocess.CalledProcessError as e: logger.error( "Dev server failed", extra={ "file": str(file), "error": str(e), "returncode": e.returncode, }, ) sys.exit(e.returncode) except FileNotFoundError: logger.error( "npx not found. Please ensure Node.js and npm are properly installed " "and added to your system PATH. You may need to restart your terminal " "after installation.", extra={"file": str(file)}, ) sys.exit(1) ``` -------------------------------- ### Install MCP Package Separately Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md If issues arise with the main MCP package installation, try installing it individually. ```bash # If you encounter any issues with the MCP package, install it separately: pip install mcp ``` -------------------------------- ### Install FastMCP Server with Custom Name Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Use the `--name` flag to provide a custom name for your installed FastMCP server. ```bash fastmcp install server.py --name "My Analytics Server" ``` -------------------------------- ### Set Environment Variables for Installation Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Set environment variables individually using the `-e` flag or load them from a `.env` file using the `-f` flag during installation. ```bash fastmcp install server.py -e API_KEY=abc123 -e DB_URL=postgres://... ``` ```bash fastmcp install server.py -f .env ``` -------------------------------- ### Dependency Injection Setup Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Defines a dataclass for dependency injection, including OpenAI client and asyncpg connection pool. ```python @dataclass class Deps: openai: AsyncOpenAI pool: asyncpg.Pool ``` -------------------------------- ### Define FastMCP Server with Dependencies Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Instantiate FastMCP with a list of dependencies that will be automatically installed when the server is installed for Claude Desktop. ```python mcp = FastMCP("My App", dependencies=["pandas", "numpy"]) ``` -------------------------------- ### Install FastMCP Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Command to install a FastMCP server, making it available for use with applications like Claude Desktop. Ensure you have the necessary environment set up. ```bash fastmcp install server.py ``` -------------------------------- ### Create a Demo MCP Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md A minimal example of an MCP server using FastMCP, defining a single 'add' tool. This illustrates the core concept of decorating functions to create tools. ```python # demo.py from fastmcp import FastMCP mcp = FastMCP("Demo 🚀") @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b ``` -------------------------------- ### Test Server with No Dependencies Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Tests the installation of a server that has no explicit dependencies. Ensures that only the default 'fastmcp' is included in the arguments. ```python def test_server_dependencies_empty(mock_config, server_file): """Test that server with no dependencies works correctly.""" runner = CliRunner() with patch("fastmcp.cli.claude.get_claude_config_path") as mock_config_path: mock_config_path.return_value = mock_config.parent result = runner.invoke(app, ["install", str(server_file)]) assert result.exit_code == 0 # Read the config file and check only fastmcp is in --with args config = json.loads(mock_config.read_text()) server = next(iter(config["mcpServers"].values())) assert server["args"].count("--with") == 1 assert "fastmcp" in server["args"] ``` -------------------------------- ### Setup MCP Handlers Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Sets up the core MCP protocol handlers for the server. This method is called during initialization. ```python def _setup_handlers(self) -> None: """Set up core MCP protocol handlers.""" self._mcp_server.list_tools()(self.list_tools) ``` -------------------------------- ### Create a Simple Echo Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md An example FastMCP server demonstrating resources, tools, and prompts. It echoes messages using different FastMCP functionalities. ```python from fastmcp import FastMCP mcp = FastMCP("Echo") @mcp.resource("echo://{message}") def echo_resource(message: str) -> str: """Echo a message as a resource""" return f"Resource echo: {message}" @mcp.tool() def echo_tool(message: str) -> str: """Echo a message as a tool""" return f"Tool echo: {message}" @mcp.prompt() def echo_prompt(message: str) -> str: """Create an echo prompt""" return f"Please process this message: {message}" ``` -------------------------------- ### Install FastMCP with pip Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Alternative installation command for FastMCP using pip. This method can be used if you are not deploying servers and only need the SDK. ```bash pip install fastmcp ``` -------------------------------- ### Install Pre-commit Hooks Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Installs pre-commit hooks for FastMCP to automatically enforce code formatting and style checks on every commit. ```bash pre-commit install ``` -------------------------------- ### Navigate to MCP Directory Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Change your current directory to the unzipped mcp-google-ads folder. Replace the example path with your actual location. ```bash # Example (replace with your actual path): cd ~/Documents/mcp-google-ads-main ``` -------------------------------- ### Install FastMCP Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Installs a FastMCP server into the Claude desktop app. Environment variables are preserved and only updated if new values are provided. Dependencies can be specified via --with and --env-var options, or loaded from a .env file. ```python env_dict |= { k: v for k, v in dotenv_values(env_file).items() if k not in os.environ } ``` -------------------------------- ### Run FastMCP Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Executes a FastMCP server directly. Ensure all dependencies are installed beforehand. Use 'fastmcp install' or 'fastmcp dev' for dependency management. ```python server.run(**kwargs) ``` -------------------------------- ### Recursive Memory System Setup Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Initializes a FastMCP server for a recursive memory system. Requires specific dependencies like pydantic-ai-slim, asyncpg, numpy, pgvector, and fastmcp. ```python # /// script # dependencies = ["pydantic-ai-slim[openai]", "asyncpg", "numpy", "pgvector", "fastmcp"] # /// # uv pip install 'pydantic-ai-slim[openai]' asyncpg numpy pgvector fastmcp """ Recursive memory system inspired by the human brain's clustering of memories. Uses OpenAI's 'text-embedding-3-small' model and pgvector for efficient similarity search. """ import asyncio import math import os from dataclasses import dataclass from datetime import datetime, timezone from pathlib import Path from typing import Annotated, Self import asyncpg import numpy as np from openai import AsyncOpenAI from pgvector.asyncpg import register_vector # Import register_vector from pydantic import BaseModel, Field from pydantic_ai import Agent from fastmcp import FastMCP MAX_DEPTH = 5 SIMILARITY_THRESHOLD = 0.7 DECAY_FACTOR = 0.99 REINFORCEMENT_FACTOR = 1.1 DEFAULT_LLM_MODEL = "openai:gpt-4o" DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small" mcp = FastMCP( ``` -------------------------------- ### Register and Get Tool Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Register a tool with the ToolManager and retrieve it to verify its properties. Ensure the tool is correctly added and its metadata is accessible. ```python manager = ToolManager() manager.add_tool(fetch_data) tool = manager.get_tool("fetch_data") assert tool is not None assert tool.name == "fetch_data" assert tool.description == "Fetch data from URL." assert tool.is_async is True assert tool.parameters["properties"]["url"]["type"] == "string" ``` -------------------------------- ### GAQL FROM Clause Example Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/gaql-google-ads-query-language.md Defines the primary resource type for the query. Only one resource can be specified, and it must have the 'RESOURCE' category. ```gaql FROM campaign ``` -------------------------------- ### Build uv run command Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Constructs a command list for 'uv run' to execute a FastMCP server. It supports adding editable installations and additional packages. ```python def _build_uv_command( file_spec: str, with_editable: Optional[Path] = None, with_packages: Optional[list[str]] = None, ) -> list[str]: """Build the uv run command that runs a FastMCP server through fastmcp run.""" cmd = ["uv"] cmd.extend(["run", "--with", "fastmcp"]) if with_editable: cmd.extend(["--with-editable", str(with_editable)]) if with_packages: for pkg in with_packages: if pkg: cmd.extend(["--with", pkg]) # Add fastmcp run command cmd.extend(["fastmcp", "run", file_spec]) return cmd ``` -------------------------------- ### GAQL Reference: Keyword Performance Source: https://context7.com/cohnen/mcp-google-ads/llms.txt Example GAQL query for analyzing keyword performance, showing text, match type, impressions, clicks, and CTR, ordered by impressions. Accessible via `gaql://reference`. ```python # 2. Keyword performance analysis """ SELECT keyword.text, keyword.match_type, metrics.impressions, metrics.clicks, metrics.ctr FROM keyword_view WHERE segments.date DURING LAST_30_DAYS ORDER BY metrics.impressions DESC """ ``` -------------------------------- ### Call Tool with List Input Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Registers and calls a tool that accepts a list of integers. This example shows how to pass list inputs to tools. ```python def sum_vals(vals: list[int]) -> int: return sum(vals) manager = ToolManager() manager.add_tool(sum_vals) # Try both with plain list and with JSON list ``` -------------------------------- ### Get Resource by URI Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieve a resource by its URI. The manager first checks concrete resources, then attempts to create one from a matching template. ```python resource = await resource_manager.get_resource("weather://london/current") ``` -------------------------------- ### GAQL Query for Basic Campaign Metrics Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Example of a Google Ads Query Language (GAQL) query to retrieve campaign names, clicks, and impressions for the last 7 days. Use this with the `run_gaql` tool. ```sql SELECT campaign.name, metrics.clicks, metrics.impressions FROM campaign WHERE segments.date DURING LAST_7DAYS ``` -------------------------------- ### Create FastMCP Server with Tools and Resources Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Demonstrates how to create a FastMCP server, add a simple addition tool, and define a dynamic greeting resource. ```python from fastmcp import FastMCP # Create an MCP server mcp = FastMCP("Demo") # Add an addition tool @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b # Add a dynamic greeting resource @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """Get a personalized greeting""" return f"Hello, {name}!" ``` -------------------------------- ### Running Server with StdIO Transport Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md This asynchronous function `run_stdio_async` initializes and runs the MCP server using the standard input/output (stdio) transport. It sets up the necessary streams and starts the MCP server's main loop. ```python async def run_stdio_async(self) -> None: """Run the server using stdio transport.""" async with stdio_server() as (read_stream, write_stream): await self._mcp_server.run( read_stream, write_stream, self._mcp_server.create_initialization_options(), ) ``` -------------------------------- ### Create a Simple Echo Server with FastMCP Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Sets up a basic FastMCP server with an 'echo' tool that returns the input text. This is useful for testing basic server functionality. ```python from fastmcp import FastMCP # Create server mcp = FastMCP("Echo Server") @mcp.tool() def echo(text: str) -> str: """Echo the input text""" return text ``` -------------------------------- ### GAQL Query for Ad Group Performance Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Example of a GAQL query to fetch ad group names and conversion metrics for ad groups with more than 100 clicks. This can be executed using the `run_gaql` tool. ```sql SELECT ad_group.name, metrics.conversions, metrics.cost_micros FROM ad_group WHERE metrics.clicks > 100 ``` -------------------------------- ### Get FastMCP Logger Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves a logger instance prefixed with 'FastMCP.'. Use this to get a logger for any module within the project. ```python def get_logger(name: str) -> logging.Logger: """Get a logger nested under FastMCP namespace. Args: name: the name of the logger, which will be prefixed with 'FastMCP.' Returns: a configured logger instance """ return logging.getLogger(f"FastMCP.{name}") ``` -------------------------------- ### GAQL Reference: Campaign Performance Source: https://context7.com/cohnen/mcp-google-ads/llms.txt Example GAQL query to retrieve campaign performance metrics, including impressions, clicks, cost, and conversions, filtered by date. Uses the MCP resource protocol `gaql://reference`. ```python # Access the GAQL reference via MCP resource protocol # Resource URI: gaql://reference # Common GAQL query patterns: # 1. Campaign performance with date filtering """ SELECT campaign.id, campaign.name, campaign.status, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions FROM campaign WHERE segments.date DURING LAST_30_DAYS ORDER BY metrics.cost_micros DESC """ ``` -------------------------------- ### Running Server with SSE Transport Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md This asynchronous function `run_sse_async` configures and runs the MCP server using the Server-Sent Events (SSE) transport. It sets up a Starlette application with routes for SSE and message handling, then starts a uvicorn server. ```python async def run_sse_async(self) -> None: """Run the server using SSE transport.""" from starlette.applications import Starlette from starlette.routing import Route sse = SseServerTransport("/messages") async def handle_sse(request): async with sse.connect_sse( request.scope, request.receive, request._send ) as streams: await self._mcp_server.run( streams[0], streams[1], self._mcp_server.create_initialization_options(), ) async def handle_messages(request): await sse.handle_post_message(request.scope, request.receive, request._send) starlette_app = Starlette( debug=self.settings.debug, routes=[ Route("/sse", endpoint=handle_sse), Route("/messages", endpoint=handle_messages, methods=["POST"]), ], ) config = uvicorn.Config( starlette_app, host=self.settings.host, port=self.settings.port, log_level=self.settings.log_level.lower(), ) server = uvicorn.Server(config) await server.serve() ``` -------------------------------- ### Initialize Database with Vector Extension Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Initializes the database by terminating existing connections, dropping and recreating the database, and then creating the 'vector' extension and the 'memories' table with a HNSW index. ```python async with pool.acquire() as conn: await conn.execute(""" SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'memory_db' AND pid <> pg_backend_pid(); """") await conn.execute("DROP DATABASE IF EXISTS memory_db;") await conn.execute("CREATE DATABASE memory_db;") finally: await pool.close() pool = await asyncpg.create_pool(DB_DSN) try: async with pool.acquire() as conn: await conn.execute("CREATE EXTENSION IF NOT EXISTS vector;") await register_vector(conn) await conn.execute(""" CREATE TABLE IF NOT EXISTS memories ( id SERIAL PRIMARY KEY, content TEXT NOT NULL, summary TEXT, importance REAL NOT NULL, access_count INT NOT NULL, timestamp DOUBLE PRECISION NOT NULL, embedding vector(1536) NOT NULL ); CREATE INDEX IF NOT EXISTS idx_memories_embedding ON memories USING hnsw (embedding vector_l2_ops); """) finally: await pool.close() ``` -------------------------------- ### Create and Configure FastMCP Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Initializes a FastMCP server instance with a given name and sets up Surge API settings. This is the entry point for defining tools and their functionalities. ```python mcp = FastMCP("Text me") surge_settings = SurgeSettings() # type: ignore ``` -------------------------------- ### Open Claude Desktop Configuration File (Mac) Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Open the Claude desktop configuration file using nano on Mac to set up the connection to Google Ads. ```bash # For Mac users: nano ~/Library/Application\ Support/Claude/claude_desktop_config.json ``` -------------------------------- ### Register and Run Basic Function with ToolManager Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Demonstrates registering a synchronous function 'add' with ToolManager and verifying its properties. Ensures parameters are correctly parsed as integers. ```python def add(a: int, b: int) -> int: """Add two numbers.""" return a + b manager = ToolManager() manager.add_tool(add) tool = manager.get_tool("add") assert tool is not None assert tool.name == "add" assert tool.description == "Add two numbers." assert tool.is_async is False assert tool.parameters["properties"]["a"]["type"] == "integer" assert tool.parameters["properties"]["b"]["type"] == "integer" ``` -------------------------------- ### Get Request ID Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves the unique ID for the current request as a string. ```python @property def request_id(self) -> str: """Get the unique ID for this request.""" return str(self.request_context.request_id) ``` -------------------------------- ### Create a FastMCP Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Instantiate the FastMCP server, optionally specifying dependencies for deployment and development. ```python from fastmcp import FastMCP # Create a named server mcp = FastMCP("My App") # Specify dependencies for deployment and development mcp = FastMCP("My App", dependencies=["pandas", "numpy"]) ``` -------------------------------- ### List All Registered Templates Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Get a list of all resource templates registered with the ResourceManager. ```python all_templates = resource_manager.list_templates() ``` -------------------------------- ### Create Virtual Environment with Python Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Alternatively, use the standard Python module to create a virtual environment if uv is not available. ```bash # OR using standard Python: python -m venv .venv ``` -------------------------------- ### List All Registered Resources Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Get a list of all resources currently managed by the ResourceManager. ```python all_resources = resource_manager.list_resources() ``` -------------------------------- ### Get Prompt by Name Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves a specific prompt from the manager using its name. ```python def get_prompt(self, name: str) -> Optional[Prompt]: """Get prompt by name.""" return self._prompts.get(name) ``` -------------------------------- ### GAQL LIMIT Clause Example Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/gaql-google-ads-query-language.md Restricts the number of results returned by the query. ```gaql LIMIT 100 ``` -------------------------------- ### Render Prompt from Function with Arguments Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Functions can accept arguments. Provide these arguments during `prompt.render()` using the `arguments` dictionary. Default values are used if arguments are not provided. ```python async def fn(name: str, age: int = 30) -> str: return f"Hello, {name}! You're {age} years old." prompt = Prompt.from_function(fn) assert await prompt.render(arguments=dict(name="World")) == [ UserMessage( content=TextContent( type="text", text="Hello, World! You're 30 years old." ) ) ] ``` -------------------------------- ### Get Unknown Resource Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Attempts to retrieve a resource that has not been added to the manager. This is expected to raise a ValueError. ```python manager = ResourceManager() with pytest.raises(ValueError, match="Unknown resource"): await manager.get_resource(AnyUrl("unknown://test")) ``` -------------------------------- ### Get Resource by URI Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves a resource from the manager using its URI. The resource must have been previously added. ```python manager = ResourceManager() resource = FileResource( uri=FileUrl(f"file://{temp_file}"), name="test", path=temp_file, ) manager.add_resource(resource) retrieved = await manager.get_resource(resource.uri) assert retrieved == resource ``` -------------------------------- ### ResourceTemplate Initialization Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Define a ResourceTemplate with a URI template, name, and optional description. This is used for dynamically creating resources. ```python ResourceTemplate( uri_template="weather://{city}/current", name="Current Weather", description="Get the current weather for a specified city." ) ``` -------------------------------- ### Get prompt by name Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves a prompt from the manager using its name. Returns None if the prompt is not found. ```python def get_prompt(self, name: str) -> Optional[Prompt]: """Get prompt by name.""" return self._prompts.get(name) ``` -------------------------------- ### Run FastMCP Server using CLI or Python/uv Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Commands to run a FastMCP server directly, either via the FastMCP CLI or using Python/uv. ```bash fastmcp run server.py ``` ```bash python server.py ``` ```bash uv run python server.py ``` -------------------------------- ### Echo Tool and Resources Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Implements an echo server with a tool, a static resource, and a templated resource. Also includes an echo prompt. ```python from fastmcp import FastMCP # Create server mcp = FastMCP("Echo Server") @mcp.tool() def echo_tool(text: str) -> str: """Echo the input text""" return text ``` ```python @mcp.resource("echo://static") def echo_resource() -> str: return "Echo!" ``` ```python @mcp.resource("echo://{text}") def echo_template(text: str) -> str: """Echo the input text""" return f"Echo: {text}" ``` ```python @mcp.prompt("echo") def echo_prompt(text: str) -> str: return text ``` -------------------------------- ### Create a mock server file for testing Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md A pytest fixture that creates a temporary Python file containing a basic FastMCP server initialization. ```python @pytest.fixture def server_file(tmp_path): """Create a server file.""" server_file = tmp_path / "server.py" server_file.write_text( """from fastmcp import FastMCP mcp = FastMCP("test") """ ) return server_file ``` -------------------------------- ### GAQL ORDER BY Clause Example Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/gaql-google-ads-query-language.md Sorts the query results. Only fields marked as 'sortable: true' can be used for sorting. ```gaql ORDER BY metrics.impressions DESC, campaign.id ``` -------------------------------- ### Run FastMCP Development Server Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Launches a web app for inspecting the FastMCP server. Ensure you have a fork set up for development. ```python This will launch a web app on http://localhost:5173/ that you can use to inspect the FastMCP server. ``` -------------------------------- ### Ensure and Upgrade pip Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md If you encounter a 'pip not found' error, ensure pip is installed and updated using the python3 module. ```bash # First ensure pip is installed and updated: python3 -m ensurepip --upgrade python3 -m pip install --upgrade pip ``` -------------------------------- ### Test File Resource Creation and Properties Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Verifies the creation of a FileResource and checks its properties like name, description, mime type, and path. ```python assert resource.name == "test" assert resource.description == "test file" assert resource.mime_type == "text/plain" # default assert resource.path == temp_file assert resource.is_binary is False # default ``` -------------------------------- ### Test Function Resource Creation Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Demonstrates the creation of a FunctionResource, verifying its URI, name, description, mime type, and associated function. ```python def my_func() -> str: return "test content" resource = FunctionResource( uri=AnyUrl("fn://test"), name="test", description="test function", fn=my_func, ) assert str(resource.uri) == "fn://test" assert resource.name == "test" assert resource.description == "test function" assert resource.mime_type == "text/plain" # default assert resource.fn == my_func ``` -------------------------------- ### Expose Desktop Directory as Resource Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Exposes the user's desktop directory as a FastMCP resource. Lists files in the desktop directory. ```python from pathlib import Path from fastmcp.server import FastMCP # Create server mcp = FastMCP("Demo") @mcp.resource("dir://desktop") def desktop() -> list[str]: """List the files in the user's desktop""" desktop = Path.home() / "Desktop" return [str(f) for f in desktop.iterdir()] ``` -------------------------------- ### Get Client ID Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves the client ID if available from the request context's metadata. Returns None if metadata is not present. ```python @property def client_id(self) -> str | None: """Get the client ID if available.""" return ( getattr(self.request_context.meta, "client_id", None) if self.request_context.meta else None ) ``` -------------------------------- ### Get Request Context Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Returns a Context object, which is valid only during an active request. Attempting to use it outside a request will result in an error. ```python def get_context(self) -> "Context": """ Returns a Context object. Note that the context will only be valid during a request; outside a request, most methods will error. """ try: request_context = self._mcp_server.request_context except LookupError: request_context = None return Context(request_context=request_context, fastmcp=self) ``` -------------------------------- ### FastMCP Server Initialization Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Initializes the FastMCP server, setting up configuration, MCP server instance, and managers for tools, resources, and prompts. It also configures logging and sets up core MCP protocol handlers. ```python class FastMCP: def __init__(self, name: str | None = None, **settings: Any): self.settings = Settings(**settings) self._mcp_server = MCPServer(name=name or "FastMCP") self._tool_manager = ToolManager( warn_on_duplicate_tools=self.settings.warn_on_duplicate_tools ) self._resource_manager = ResourceManager( warn_on_duplicate_resources=self.settings.warn_on_duplicate_resources ) self._prompt_manager = PromptManager( warn_on_duplicate_prompts=self.settings.warn_on_duplicate_prompts ) self.dependencies = self.settings.dependencies # Set up MCP protocol handlers self._setup_handlers() # Configure logging configure_logging(self.settings.log_level) ``` -------------------------------- ### Get Database Schema Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves the SQL schema for all tables in the 'database.db' SQLite file. Ensure 'database.db' exists and contains tables. ```python def get_schema() -> str: """Provide the database schema as a resource""" conn = sqlite3.connect("database.db") schema = conn.execute( "SELECT sql FROM sqlite_master WHERE type='table'" ).fetchall() return "\n".join(sql[0] for sql in schema if sql[0]) ``` -------------------------------- ### Create Temporary Directory with Test Files Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md A pytest fixture that creates a temporary directory and populates it with example files for testing purposes. ```python def test_dir(tmp_path_factory) -> Path: """Create a temporary directory with test files.""" tmp = tmp_path_factory.mktemp("test_files") # Create test files (tmp / "example.py").write_text("print('hello world')") (tmp / "readme.md").write_text("# Test Directory\nThis is a test.") (tmp / "config.json").write_text('{"test": true}') return tmp ``` -------------------------------- ### Mount Local Code for Live Updates Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Use `--with-editable .` to mount local code for live updates during development. ```bash fastmcp dev server.py --with-editable . ``` -------------------------------- ### GAQL WHERE Clause Example Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/gaql-google-ads-query-language.md Filters the query results based on specified conditions. Only fields marked as 'filterable: true' can be used for filtering. ```gaql WHERE campaign.status = 'ENABLED' AND metrics.impressions > 1000 AND segments.date DURING LAST_30_DAYS ``` -------------------------------- ### Activate Virtual Environment (Windows) Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Activate the created virtual environment on Windows systems. ```bash # On Windows: .venv\Scripts\activate ``` -------------------------------- ### GAQL WHERE Clause with Literal Date Range Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/gaql-google-ads-query-language.md Filters results using a specific date range defined by start and end dates. ```gaql WHERE segments.date BETWEEN '2020-01-01' AND '2020-01-31' ``` -------------------------------- ### Display FastMCP Version Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieves and prints the installed version of the 'fastmcp' package. If the package is not found, it prints an unknown version message and exits. ```python try: version = importlib.metadata.version("fastmcp") print(f"FastMCP version {version}") except importlib.metadata.PackageNotFoundError: print("FastMCP version unknown (package not installed)") sys.exit(1) ``` -------------------------------- ### Call Tool with Context Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Demonstrates calling a tool with context provided. Ensure the tool is added to the manager before calling. ```python manager = ToolManager() manager.add_tool(tool_with_context) # Should not raise an error when context is not provided result = await manager.call_tool("tool_with_context", {"x": 42}) ``` -------------------------------- ### Get a Tool by Name Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Retrieve a registered tool from the `ToolManager` using its unique name. Returns `None` if no tool with the specified name is found. ```python def get_tool(self, name: str) -> Optional[Tool]: """Get tool by name.""" return self._tools.get(name) ``` -------------------------------- ### GAQL SELECT Clause Example Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/gaql-google-ads-query-language.md Specifies the fields to be retrieved in the query results. Only fields marked as 'selectable: true' in GoogleAdsField metadata can be used. ```gaql SELECT campaign.id, campaign.name, metrics.impressions, segments.device ``` -------------------------------- ### FastMCP CLI Initialization Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Initializes the FastMCP CLI package by importing the 'app' object from the 'cli' module. Includes a standard Python entry point check for direct execution. ```python """FastMCP CLI package.""" from .cli import app if __name__ == "__main__": app() ``` -------------------------------- ### Activate Virtual Environment (Mac/Linux) Source: https://github.com/cohnen/mcp-google-ads/blob/main/README.md Activate the created virtual environment on macOS or Linux systems. ```bash # On Mac/Linux: source .venv/bin/activate ``` -------------------------------- ### Define a Simple String Prompt Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Define a simple prompt as a string template using the @mcp.prompt decorator. This can be used to guide LLM interactions. ```python @mcp.prompt() def review_code(code: str) -> str: return f"Please review this code:\n\n{code}" ``` -------------------------------- ### Initialize PromptManager and Prompt Classes Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Imports `Prompt` and `PromptManager` from their respective modules. These are essential for managing and defining prompts within the FastMCP library. ```python from .base import Prompt from .manager import PromptManager __all__ = ["Prompt", "PromptManager"] ``` -------------------------------- ### Take Screenshot with FastMCP Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Defines a tool that captures a screenshot of the user's screen and returns it as a JPEG image. Requires 'pyautogui' and 'Pillow' to be installed. ```python import io from fastmcp import FastMCP, Image # Create server mcp = FastMCP("Screenshot Demo", dependencies=["pyautogui", "Pillow"]) @mcp.tool() def take_screenshot() -> Image: """ Take a screenshot of the user's screen and return it as an image. Use this tool anytime the user wants you to look at something they're doing. """ import pyautogui buffer = io.BytesIO() # if the file exceeds ~1MB, it will be rejected by Claude screenshot = pyautogui.screenshot() screenshot.convert("RGB").save(buffer, format="JPEG", quality=60, optimize=True) return Image(data=buffer.getvalue(), format="jpeg") ``` -------------------------------- ### Initialize ResourceManager Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Instantiate the ResourceManager to manage resources. Optionally, disable warnings for duplicate resources. ```python resource_manager = ResourceManager(warn_on_duplicate_resources=False) ``` -------------------------------- ### Define an HTTP Request Tool Source: https://github.com/cohnen/mcp-google-ads/blob/main/docs/fastmcp.md Define an asynchronous tool that fetches data from an external HTTP API using httpx. Ensure httpx is installed. ```python import httpx @mcp.tool() async def fetch_weather(city: str) -> str: """Fetch current weather for a city""" async with httpx.AsyncClient() as client: response = await client.get( f"https://api.weather.com/{city}" ) return response.text ```