[{'Text': 'Found 8 matches:\n\n## Matches in point-topic-mcp/src/point_topic_mcp/auth/__init__.py\n\n### L35-40\n```\nfrom point_topic_mcp.auth.middleware import (\n    PermissionMiddleware,\n    get_user_permissions,\n    is_pt_admin,\n    check_tool_access,\n)\n```\n\n### L52-62\n```\n__all__ = [\n    # Decorators\n    "public",\n    "is_public_tool",\n    "PUBLIC_TOOLS",\n    "requires_permissions",\n    "get_tool_permissions",\n    "has_tool_permissions",\n    "TOOL_PERMISSIONS",\n    # Middleware\n    "PermissionMiddleware",\n```\n\n11 lines remaining in ancestor node. Read the file to see all.\n\n## Matches in point-topic-mcp/src/point_topic_mcp/auth/middleware.py\n\n### class PermissionMiddleware › L142-152\n```\nclass PermissionMiddleware(Middleware):\n    """Middleware that enforces permission-based access control.\n\n    This middleware filters tools based on user permissions from Auth0 JWT tokens.\n    It implements three-tier access:\n        - Unauthenticated: Only @public tools visible\n        - Authenticated: @public + matching @requires_permissions\n        - ptAdmin: All tools visible\n\n    Uses on_list_tools to filter visible tools per-user.\n    Uses on_call_tool as defense-in-depth (should rarely trigger if filtering works).\n```\n\n78 lines remaining in ancestor node. Read the file to see all.\n\n### L233-238\n```\n__all__ = [\n    "PermissionMiddleware",\n    "get_user_permissions",\n    "is_pt_admin",\n    "check_tool_access",\n]\n```\n\n## Matches in point-topic-mcp/src/point_topic_mcp/tools/__init__.py\n\n### L1-11\n```\n"""MCP tools module with auto-discovery and registration.\n\nThis module registers ALL tools at server startup.\nTool names are prefixed with the module name (e.g. database_tools_describe_table)\nfor easier agent understanding of which tool file provides each capability.\nPermission-based access control is handled by PermissionMiddleware\nwhich filters the tool list per-user via the on_list_tools hook.\n\nAccess Levels (enforced by middleware):\n1. Unauthenticated → Only @public tools visible\n2. Authenticated (not ptAdmin) → @public + matching @requires_permissions\n```\n\n11 lines remaining in ancestor node. Read the file to see all.\n\n### def register_tools › L118-128\n```\n    """Register all MCP tools by auto-discovering functions in tool modules.\n\n    Automatically finds all Python modules in the tools directory and registers\n    every public function (not starting with _) as an MCP tool.\n\n    ALL tools are registered - access control is handled by PermissionMiddleware\n    which filters the visible tool list per-user when clients request tools/list.\n\n    Just create a .py file with tool functions - the middleware handles permissions!\n\n    Args:\n```\n\n2 lines remaining in ancestor node. Read the file to see all.\n\n### def register_tools › L132-143\n```\n    try:\n        from point_topic_mcp.auth import PermissionMiddleware\n        from point_topic_mcp.auth.decorators import PUBLIC_TOOLS, TOOL_PERMISSIONS\n\n        mcp.add_middleware(PermissionMiddleware())\n        print("[MCP] Permission middleware enabled")\n\n        # Migrate auth registries to use prefixed names (middleware checks by tool name)\n        tools, _ = _discover_tools()\n        for prefixed_name, tool_func in tools:\n            name = tool_func.__name__\n            if name in PUBLIC_TOOLS:\n```\n\n6 lines remaining in ancestor node. Read the file to see all.\n\n## Matches in point-topic-mcp/tests/test_permissions.py\n\n### L9-19\n```\nfrom point_topic_mcp.auth import (\n    public,\n    requires_permissions,\n    is_public_tool,\n    get_tool_permissions,\n    has_tool_permissions,\n    PUBLIC_TOOLS,\n    TOOL_PERMISSIONS,\n    PermissionMiddleware,\n    is_pt_admin,\n    check_tool_access,\n```\n\n1 lines remaining in ancestor node. Read the file to see all.\n'}]