Skip to Content
ReferencesArcade MCPPythonResources

Resources

resources expose data to clients through URI-addressable endpoints. MCPApp provides build-time methods to register static resources, file-backed resources, and dynamic resource handlers — including URI templates with parameters.

Basic usage

Python
import json from arcade_mcp_server import MCPApp app = MCPApp(name="my_server", version="1.0.0") @app.resource( "config://app/settings", name="App Settings", description="Current application settings", mime_type="application/json", ) def app_settings(uri: str) -> str: return json.dumps({"debug": False, "version": "1.0.0"}) if __name__ == "__main__": app.run()

Registration methods

resource

Python
@app.resource( uri, name=None, title=None, description=None, mime_type=None, annotations=None, meta=None, ) def handler(uri: str) -> str: ...

Decorator for registering a resource handler. If the URI contains template parameters (e.g., {slug}), the resource is registered as a ResourceTemplate and the handler receives the extracted parameters as keyword arguments.

If name is not provided, it defaults to the function name.

Parameters:

NameTypeDescriptionDefault
uristrResource URI or URI templaterequired
namestr | NoneDisplay name for the resourceFunction name
titlestr | NoneHuman-readable titleNone
descriptionstr | NoneResource descriptionNone
mime_typestr | NoneMIME type of the resource contentNone
annotationsAnnotations | NoneResource annotations (audience, priority)None
metadict[str, Any] | NoneArbitrary metadata exposed to clients in _metaNone

add_resource

Python
app.add_resource( uri, name=None, title=None, description=None, mime_type=None, handler=None, annotations=None, meta=None, )

Imperative form of @app.resource. Registers a resource or resource template at build time.

Parameters:

NameTypeDescriptionDefault
uristrResource URI or URI templaterequired
namestr | NoneDisplay name for the resourceNone
titlestr | NoneHuman-readable titleNone
descriptionstr | NoneResource descriptionNone
mime_typestr | NoneMIME type of the resource contentNone
handlerCallable[..., Any] | NoneFunction that returns the resource contentNone
annotationsAnnotations | NoneResource annotations (audience, priority)None
metadict[str, Any] | NoneArbitrary metadata exposed to clients in _metaNone

add_text_resource

Python
app.add_text_resource( uri, text="...", name=None, title=None, description=None, mime_type="text/plain", )

Convenience method for registering a static text resource. No handler function is needed.

Parameters:

NameTypeDescriptionDefault
uristrResource URI (must not be a template)required
textstrThe static text contentrequired
namestr | NoneDisplay name for the resourceNone
titlestr | NoneHuman-readable titleNone
descriptionstr | NoneResource descriptionNone
mime_typestrMIME type of the content'text/plain'

Raises ValueError if uri contains template parameters (e.g., {slug}). Use @app.resource or add_resource for dynamic resources.

add_file_resource

Python
app.add_file_resource( uri, path="...", name=None, title=None, description=None, mime_type=None, )

Convenience method for registering a file-backed resource. Text files are served as TextResourceContents. Binary files (detected via UnicodeDecodeError) are served as BlobResourceContents with base64 encoding.

Parameters:

NameTypeDescriptionDefault
uristrResource URI (must not be a template)required
pathstr | PathPath to the file on diskrequired
namestr | NoneDisplay name for the resourceNone
titlestr | NoneHuman-readable titleNone
descriptionstr | NoneResource descriptionNone
mime_typestr | NoneMIME type (auto-detected if not provided)None

Raises ValueError if uri contains template parameters (e.g., {slug}). Use @app.resource or add_resource for dynamic resources.

URI templates

URIs that contain {param} or {param*} are registered as resource templates. When a client reads a URI that matches the template, the server extracts the parameters and passes them to the handler as keyword arguments.

Syntax

PatternMatchesExample URIExtracted value
{param}A single path segment (no /)kb://articles/{slug} matching kb://articles/helloslug="hello"
{param*}One or more segments (greedy, crosses /)kb://docs/{path*} matching kb://docs/guides/setuppath="guides/setup"

Template handler signatures

Template handlers receive the full URI as the first argument and the extracted parameters as keyword arguments:

Python
@app.resource("kb://articles/{slug}") def article_by_slug(uri: str, slug: str) -> str: ... @app.resource("kb://{category}/{slug}") def article_by_category(uri: str, category: str, slug: str) -> str: ... @app.resource("kb://docs/{path*}") def docs_tree(uri: str, path: str) -> str: ...

Handler return types

Resource handlers can return several types. The server coerces them into the appropriate content type:

Return typeResult
strTextResourceContents
bytesBlobResourceContents (base64-encoded)
dict with "text" keyTextResourceContents
dict with "blob" keyBlobResourceContents
listPassed through as-is (for multiple content items)
OtherTextResourceContents via str()

Async handlers are fully supported:

Python
@app.resource("data://users", mime_type="application/json") async def list_users(uri: str) -> str: users = await fetch_users() return json.dumps(users)

Annotations

Use the Annotations class to attach audience and priority metadata to a resource:

Python
from arcade_mcp_server import Annotations, MCPApp app = MCPApp(name="my_server", version="1.0.0") @app.resource( "kb://announcements/pinned", name="Pinned Announcement", annotations=Annotations(audience=["user"], priority=1.0), ) def pinned_announcement(uri: str) -> str: return "All-hands meeting this Friday at 3 PM."

Examples

Static text resource

Python
from arcade_mcp_server import MCPApp app = MCPApp(name="my_server", version="1.0.0") app.add_text_resource( "kb://readme", text="Welcome to the Knowledge Base.", name="README", description="Welcome text for the knowledge base", )

File-backed resource

Python
from pathlib import Path from arcade_mcp_server import MCPApp app = MCPApp(name="my_server", version="1.0.0") app.add_file_resource( "config://pyproject", path=Path("pyproject.toml"), name="Project Config", description="The pyproject.toml for this project", mime_type="text/plain", )

Dynamic resource with URI template

Python
import json from arcade_mcp_server import MCPApp app = MCPApp(name="my_server", version="1.0.0") ARTICLES = { "hello-world": {"title": "Hello World", "body": "Welcome!"}, "getting-started": {"title": "Getting Started", "body": "Let's begin."}, } @app.resource( "kb://articles/index", name="Article Index", description="List of all articles", mime_type="application/json", ) def article_index(uri: str) -> str: return json.dumps(list(ARTICLES.keys())) @app.resource( "kb://articles/{slug}", name="Article by Slug", description="Retrieve an article by its slug", mime_type="application/json", ) def article_by_slug(uri: str, slug: str) -> str: article = ARTICLES.get(slug) if not article: return json.dumps({"error": "Not found"}) return json.dumps(article, indent=2) if __name__ == "__main__": app.run()

Resource with custom metadata

Python
from arcade_mcp_server import MCPApp app = MCPApp(name="my_server", version="1.0.0") @app.resource( "kb://articles/api-guidelines/metadata", name="API Guidelines Metadata", meta={"tags": ["api", "engineering"], "version": 2, "reviewed": True}, ) def article_metadata(uri: str) -> str: return "API guidelines metadata"

Combining tools and resources

Python
import json from typing import Annotated from arcade_mcp_server import MCPApp app = MCPApp(name="my_server", version="1.0.0") ARTICLES = { "hello": {"title": "Hello", "body": "Hello World!"}, } @app.resource( "kb://articles/{slug}", name="Article by Slug", mime_type="application/json", ) def get_article_resource(uri: str, slug: str) -> str: return json.dumps(ARTICLES.get(slug, {})) @app.tool def search_articles(query: Annotated[str, "Search query"]) -> str: """Search articles by title.""" matches = [ slug for slug, article in ARTICLES.items() if query.lower() in article["title"].lower() ] return json.dumps(matches) if __name__ == "__main__": app.run()
Last updated on