From 21a5a92cd97091c7616d2b432c5d0f71f5c16508 Mon Sep 17 00:00:00 2001 From: Tito0015 Date: Sun, 4 Oct 2026 01:41:53 -0400 Subject: [PATCH] Python: model MCP and FastMCP server handler parameters as remote flow sources --- .../codeql/reusables/supported-frameworks.rst | 2 + .../2026-10-04-mcp-remote-sources.md | 4 + python/ql/lib/semmle/python/Frameworks.qll | 1 + .../ql/lib/semmle/python/frameworks/Mcp.qll | 137 ++++++++++++++++++ .../RemoteFlowSources.expected | 12 ++ .../remote-flow-sources/RemoteFlowSources.ql | 6 + .../dataflow/remote-flow-sources/mcp_test.py | 81 +++++++++++ 7 files changed, 243 insertions(+) create mode 100644 python/ql/lib/change-notes/2026-10-04-mcp-remote-sources.md create mode 100644 python/ql/lib/semmle/python/frameworks/Mcp.qll create mode 100644 python/ql/test/library-tests/dataflow/remote-flow-sources/RemoteFlowSources.expected create mode 100644 python/ql/test/library-tests/dataflow/remote-flow-sources/RemoteFlowSources.ql create mode 100644 python/ql/test/library-tests/dataflow/remote-flow-sources/mcp_test.py diff --git a/docs/codeql/reusables/supported-frameworks.rst b/docs/codeql/reusables/supported-frameworks.rst index 6fa32547d05a..78ca5754d7e2 100644 --- a/docs/codeql/reusables/supported-frameworks.rst +++ b/docs/codeql/reusables/supported-frameworks.rst @@ -226,6 +226,8 @@ and the CodeQL library pack ``codeql/python-all`` (`changelog str: + return command + + +@mcp_app.tool +def bare_tool(command: str) -> str: + return command + + +@mcp_sdk.prompt() +def sdk_prompt(topic: str, *, style: str = "short") -> str: + return topic + style + + +@mcp_v2.resource("notes://{name}") +def v2_resource(name: str) -> str: + return name + + +async def async_fetch(url: str) -> str: + return url + + +mcp_app.add_tool(async_fetch) + + +def added_via_add(url: str) -> str: + return url + + +mcp_sdk.add_tool(fn=added_via_add) + + +@standalone_tool +def module_tool(cmd: str) -> str: + return cmd + + +@standalone_tool() +def module_tool_called(cmd: str) -> str: + return cmd + + +@other_decorator +@mcp_app.tool() +def stacked_decorator(cmd: str) -> str: + return cmd + + +def not_registered(value: str) -> str: + return value + + +@mcp_app.tool() +def with_context(ctx: Context, data: str) -> str: + return data + + +class Service: + def __init__(self): + self.mcp = FastMCP("svc") + + def register(self): + @self.mcp.tool() + def instance_lookup(host: str) -> str: + return host