{"record":{"id":"9a61b8cc1de29439","repo":"PrefectHQ/fastmcp","slug":"visibility-cannot-be-set-on-resources-it-only-ap","errorCode":null,"errorMessage":"visibility cannot be set on resources — it only applies to tools.","messagePattern":"visibility cannot be set on resources — it only applies to tools\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/server.py","lineNumber":2061,"sourceCode":"                \"The @resource decorator was used incorrectly. \"\n                \"It requires a URI as the first argument. \"\n                \"Use @resource('uri') instead of @resource\"\n            )\n\n        # Apply default MIME type for ui:// scheme resources\n        mime_type = resolve_ui_mime_type(uri, mime_type)\n\n        # Validate app config for resources — resource_uri and visibility\n        # don't apply since the resource itself is the UI\n        if isinstance(app, AppConfig):\n            if app.resource_uri is not None:\n                raise ValueError(\n                    \"resource_uri cannot be set on resources — \"\n                    \"the resource itself is the UI. \"\n                    \"Use resource_uri on tools to point to a UI resource.\"\n                )\n            if app.visibility is not None:\n                raise ValueError(\n                    \"visibility cannot be set on resources — it only applies to tools.\"\n                )\n\n        # Merge app config into meta[\"ui\"] (wire format) before passing to provider\n        if app is not None and app is not False:\n            meta = dict(meta) if meta else {}\n            if app is True:\n                meta[\"ui\"] = True\n            else:\n                meta[\"ui\"] = app_config_to_meta_dict(app)\n\n        # Delegate to LocalProvider with server-level defaults\n        inner_decorator = self._local_provider.resource(\n            uri,\n            name=name,\n            version=version,\n            title=title,\n            description=description,","sourceCodeStart":2043,"sourceCodeEnd":2079,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/server.py#L2043-L2079","documentation":"The @mcp.resource decorator rejects an AppConfig with a non-None visibility setting, because visibility controls only apply to tools, not resources. Configuration-time ValueError.","triggerScenarios":"Passing app=AppConfig(visibility=\"private\" or similar) to mcp.resource() or a resource template decorator.","commonSituations":"Sharing one AppConfig across tools and resources; assuming visibility governs resource access control (it doesn't — use auth/middleware for resources).","solutions":["Remove visibility from the AppConfig on the resource","Control resource access via providers/middleware/auth instead of visibility","Give resources their own AppConfig (or app=None/False) separate from tools"],"exampleFix":"// before\n@mcp.resource(\"data://metrics\", app=AppConfig(visibility=\"private\"))\ndef metrics(): ...\n// after\n@mcp.resource(\"data://metrics\")\ndef metrics(): ...","handlingStrategy":"validation","validationCode":"if isinstance(app, AppConfig) and app.visibility is not None:\n    raise ValueError(\"visibility is tool-only; remove it for resources\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Don't share one AppConfig across tool and resource decorators","Use auth/middleware for resource access control","Review AppConfig fields against component type before use"],"tags":["python","resources","config","visibility"],"backgroundTag":"invalid-app-config-for-component","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}