diff --git a/.funcignore b/.funcignore new file mode 100644 index 0000000000..9966315f80 --- /dev/null +++ b/.funcignore @@ -0,0 +1,8 @@ +.git* +.vscode +__azurite_db*__.json +__blobstorage__ +__queuestorage__ +local.settings.json +test +.venv \ No newline at end of file diff --git a/.gitignore b/.gitignore index 55f472ee2d..7685fc4ac8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,90 +1,135 @@ -log/ -xhtml/ -packages/ -obj/ -_site/ -Tools/NuGet/ -_site/ -.optemp/ -.vscode -.DS_Store - -.openpublishing.build.mdproj -.openpublishing.buildcore.ps1 -packages.config -*.tmp - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015 cache/options directory -.vs/ - -# DNX -project.lock.json -project.fragment.lock.json -artifacts/ - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: *.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap -.markdownlint.json - -# Stop ReadMe file from syncing to maintain separate public and private Readme notes -README.md +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don’t work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Azure Functions artifacts +bin +obj +appsettings.json +local.settings.json + +# Azurite artifacts +__blobstorage__ +__queuestorage__ +__azurite_db*__.json +.python_packages \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..3f63eb97df --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "ms-azuretools.vscode-azurefunctions", + "ms-python.python" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..f380c98d8c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Python Functions", + "type": "debugpy", + "request": "attach", + "connect": { + "host": "localhost", + "port": 9091 + }, + "preLaunchTask": "func: host start" + } + ] +} \ No newline at end of file diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 0000000000..545cee3614 --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,18 @@ +{ + "servers": { + "microsoft/markitdown": { + "type": "stdio", + "command": "uvx", + "args": [ + "markitdown-mcp@0.0.1a4" + ], + "gallery": "https://api.mcp.github.com", + "version": "1.0.0" + }, + "windows-dev-docs-local-server": { + "type": "http", + "url": "http://localhost:7071/mcp" + } + }, + "inputs": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..4fc76e2f23 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "azureFunctions.projectLanguage": "Python", + "azureFunctions.projectRuntime": "~4", + "debug.internalConsoleOptions": "neverOpen", + "azureFunctions.mcpProjectType": "SelfHostedMcpServer", + "azureFunctions.deploySubpath": ".", + "azureFunctions.scmDoBuildDuringDeployment": true, + "azureFunctions.pythonVenv": ".venv" +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..a450213c15 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,27 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "func", + "label": "func: host start", + "command": "host start", + "problemMatcher": "$func-python-watch", + "isBackground": true, + "dependsOn": "pip install (functions)" + }, + { + "label": "pip install (functions)", + "type": "shell", + "osx": { + "command": "${config:azureFunctions.pythonVenv}/bin/python -m pip install -r requirements.txt" + }, + "windows": { + "command": "${config:azureFunctions.pythonVenv}/Scripts/python -m pip install -r requirements.txt" + }, + "linux": { + "command": "${config:azureFunctions.pythonVenv}/bin/python -m pip install -r requirements.txt" + }, + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/hello.py b/hello.py new file mode 100644 index 0000000000..b638ec4c93 --- /dev/null +++ b/hello.py @@ -0,0 +1,24 @@ +from typing import Any +import sys +import logging +from mcp.server.fastmcp import FastMCP + +# Reduce MCP SDK logging verbosity +logging.getLogger("mcp").setLevel(logging.WARNING) + +# Initialize FastMCP server +mcp = FastMCP("weather", stateless_http=True) + +# Add a simple tool to demonstrate the server +@mcp.tool() +def greet(name: str = "World") -> str: + """Greet someone by name.""" + return f"Hello, {name}!" + +if __name__ == "__main__": + try: + # Initialize and run the server + print("Starting MCP server...") + mcp.run(transport="streamable-http") + except Exception as e: + print(f"Error while running MCP server: {e}", file=sys.stderr) \ No newline at end of file diff --git a/host.json b/host.json new file mode 100644 index 0000000000..2a1f2ff0fc --- /dev/null +++ b/host.json @@ -0,0 +1,11 @@ +{ + "version": "2.0", + "configurationProfile": "mcp-custom-handler", + "customHandler": { + "description": { + "defaultExecutablePath": "python", + "arguments": ["hello.py"] + }, + "port": "8000" + } +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..20f56ece67 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "1031weather-scaffold-test" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "httpx>=0.28.1", + "mcp[cli]>=1.20.0", +]