From 7453e70cd0465c7138dae354cc36d976665ecbe6 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Thu, 31 Jul 2025 17:27:11 -0700 Subject: [PATCH 01/15] Implement prefix based matching for list resources / templates methods --- .../mcp_simple_resource/server.py | 4 +- src/mcp/client/session.py | 18 ++- .../fastmcp/resources/resource_manager.py | 24 ++-- src/mcp/server/fastmcp/resources/templates.py | 38 ++++++ src/mcp/server/fastmcp/server.py | 21 +++- src/mcp/server/lowlevel/server.py | 12 +- src/mcp/types.py | 22 +++- tests/issues/test_152_resource_mime_type.py | 2 +- .../resources/test_resource_manager.py | 94 +++++++++++++++ .../resources/test_resource_template.py | 114 ++++++++++++++++++ tests/server/test_session.py | 2 +- tests/shared/test_memory.py | 3 +- 12 files changed, 323 insertions(+), 31 deletions(-) diff --git a/examples/servers/simple-resource/mcp_simple_resource/server.py b/examples/servers/simple-resource/mcp_simple_resource/server.py index cef29b851..57fc60b69 100644 --- a/examples/servers/simple-resource/mcp_simple_resource/server.py +++ b/examples/servers/simple-resource/mcp_simple_resource/server.py @@ -32,7 +32,9 @@ def main(port: int, transport: str) -> int: app = Server("mcp-simple-resource") @app.list_resources() - async def list_resources() -> list[types.Resource]: + async def list_resources( + request: types.ListResourcesRequest, + ) -> list[types.Resource]: return [ types.Resource( uri=FileUrl(f"file:///{name}.txt"), diff --git a/src/mcp/client/session.py b/src/mcp/client/session.py index 1853ce7c1..0c69436bf 100644 --- a/src/mcp/client/session.py +++ b/src/mcp/client/session.py @@ -221,25 +221,35 @@ async def set_logging_level(self, level: types.LoggingLevel) -> types.EmptyResul types.EmptyResult, ) - async def list_resources(self, cursor: str | None = None) -> types.ListResourcesResult: + async def list_resources(self, prefix: str | None = None, cursor: str | None = None) -> types.ListResourcesResult: """Send a resources/list request.""" + params = None + if cursor is not None or prefix is not None: + params = types.ListResourcesRequestParams(prefix=prefix, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListResourcesRequest( method="resources/list", - params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None, + params=params, ) ), types.ListResourcesResult, ) - async def list_resource_templates(self, cursor: str | None = None) -> types.ListResourceTemplatesResult: + async def list_resource_templates( + self, + prefix: str | None = None, + cursor: str | None = None, + ) -> types.ListResourceTemplatesResult: """Send a resources/templates/list request.""" + params = None + if cursor is not None or prefix is not None: + params = types.ListResourceTemplatesRequestParams(prefix=prefix, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListResourceTemplatesRequest( method="resources/templates/list", - params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None, + params=params, ) ), types.ListResourceTemplatesResult, diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index 35e4ec04d..7cc62b034 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -86,12 +86,18 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: raise ValueError(f"Unknown resource: {uri}") - def list_resources(self) -> list[Resource]: - """List all registered resources.""" - logger.debug("Listing resources", extra={"count": len(self._resources)}) - return list(self._resources.values()) - - def list_templates(self) -> list[ResourceTemplate]: - """List all registered templates.""" - logger.debug("Listing templates", extra={"count": len(self._templates)}) - return list(self._templates.values()) + def list_resources(self, prefix: str | None = None) -> list[Resource]: + """List all registered resources, optionally filtered by URI prefix.""" + resources = list(self._resources.values()) + if prefix: + resources = [r for r in resources if str(r.uri).startswith(prefix)] + logger.debug("Listing resources", extra={"count": len(resources), "prefix": prefix}) + return resources + + def list_templates(self, prefix: str | None = None) -> list[ResourceTemplate]: + """List all registered templates, optionally filtered by URI template prefix.""" + templates = list(self._templates.values()) + if prefix: + templates = [t for t in templates if t.matches_prefix(prefix)] + logger.debug("Listing templates", extra={"count": len(templates), "prefix": prefix}) + return templates diff --git a/src/mcp/server/fastmcp/resources/templates.py b/src/mcp/server/fastmcp/resources/templates.py index b1c7b2711..54b04dde3 100644 --- a/src/mcp/server/fastmcp/resources/templates.py +++ b/src/mcp/server/fastmcp/resources/templates.py @@ -63,6 +63,44 @@ def matches(self, uri: str) -> dict[str, Any] | None: return match.groupdict() return None + def matches_prefix(self, prefix: str) -> bool: + """Check if this template could match URIs with the given prefix.""" + + # First, simple check: does the template itself start with the prefix? + if self.uri_template.startswith(prefix): + return True + + template_segments = self.uri_template.split("/") + prefix_segments = prefix.split("/") + + # Handle trailing slash - it creates an empty last segment + has_trailing_slash = prefix.endswith("/") and prefix_segments[-1] == "" + if has_trailing_slash: + # Remove the empty segment for comparison + prefix_segments = prefix_segments[:-1] + # Template must have more segments to generate something "under" this path + if len(template_segments) <= len(prefix_segments): + return False + else: + # Without trailing slash, prefix can't have more segments than template + if len(prefix_segments) > len(template_segments): + return False + + # Compare each segment + for i, prefix_seg in enumerate(prefix_segments): + template_seg = template_segments[i] + + # If template segment is a parameter, it can match any value + if template_seg.startswith("{") and template_seg.endswith("}"): + continue + + # If both are literals, they must match exactly + if template_seg != prefix_seg: + return False + + # All prefix segments matched + return True + async def create_resource(self, uri: str, params: dict[str, Any]) -> Resource: """Create a resource from the template with the given parameters.""" try: diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 924baaa9b..aba2bcf0c 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -21,6 +21,7 @@ from starlette.routing import Mount, Route from starlette.types import Receive, Scope, Send +from mcp import types from mcp.server.auth.middleware.auth_context import AuthContextMiddleware from mcp.server.auth.middleware.bearer_auth import BearerAuthBackend, RequireAuthMiddleware from mcp.server.auth.provider import OAuthAuthorizationServerProvider, ProviderTokenVerifier, TokenVerifier @@ -297,10 +298,12 @@ async def call_tool(self, name: str, arguments: dict[str, Any]) -> Sequence[Cont context = self.get_context() return await self._tool_manager.call_tool(name, arguments, context=context, convert_result=True) - async def list_resources(self) -> list[MCPResource]: - """List all available resources.""" - - resources = self._resource_manager.list_resources() + async def list_resources(self, request: types.ListResourcesRequest | None = None) -> list[MCPResource]: + """List all available resources, optionally filtered by prefix.""" + prefix = None + if request and request.params: + prefix = request.params.prefix + resources = self._resource_manager.list_resources(prefix=prefix) return [ MCPResource( uri=resource.uri, @@ -312,8 +315,14 @@ async def list_resources(self) -> list[MCPResource]: for resource in resources ] - async def list_resource_templates(self) -> list[MCPResourceTemplate]: - templates = self._resource_manager.list_templates() + async def list_resource_templates( + self, request: types.ListResourceTemplatesRequest | None = None + ) -> list[MCPResourceTemplate]: + """List all available resource templates, optionally filtered by prefix.""" + prefix = None + if request and request.params: + prefix = request.params.prefix + templates = self._resource_manager.list_templates(prefix=prefix) return [ MCPResourceTemplate( uriTemplate=template.uri_template, diff --git a/src/mcp/server/lowlevel/server.py b/src/mcp/server/lowlevel/server.py index ab6a3d15c..0100cdb50 100644 --- a/src/mcp/server/lowlevel/server.py +++ b/src/mcp/server/lowlevel/server.py @@ -259,11 +259,11 @@ async def handler(req: types.GetPromptRequest): return decorator def list_resources(self): - def decorator(func: Callable[[], Awaitable[list[types.Resource]]]): + def decorator(func: Callable[[types.ListResourcesRequest], Awaitable[list[types.Resource]]]): logger.debug("Registering handler for ListResourcesRequest") - async def handler(_: Any): - resources = await func() + async def handler(request: types.ListResourcesRequest): + resources = await func(request) return types.ServerResult(types.ListResourcesResult(resources=resources)) self.request_handlers[types.ListResourcesRequest] = handler @@ -272,11 +272,11 @@ async def handler(_: Any): return decorator def list_resource_templates(self): - def decorator(func: Callable[[], Awaitable[list[types.ResourceTemplate]]]): + def decorator(func: Callable[[types.ListResourceTemplatesRequest], Awaitable[list[types.ResourceTemplate]]]): logger.debug("Registering handler for ListResourceTemplatesRequest") - async def handler(_: Any): - templates = await func() + async def handler(request: types.ListResourceTemplatesRequest): + templates = await func(request) return types.ServerResult(types.ListResourceTemplatesResult(resourceTemplates=templates)) self.request_handlers[types.ListResourceTemplatesRequest] = handler diff --git a/src/mcp/types.py b/src/mcp/types.py index 98fefa080..078bbc871 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -63,6 +63,20 @@ class PaginatedRequestParams(RequestParams): """ +class ListResourcesRequestParams(PaginatedRequestParams): + """Parameters for listing resources with optional prefix filtering.""" + + prefix: str | None = None + """Optional prefix to filter resources by URI.""" + + +class ListResourceTemplatesRequestParams(PaginatedRequestParams): + """Parameters for listing resource templates with optional prefix filtering.""" + + prefix: str | None = None + """Optional prefix to filter resource templates by URI template.""" + + class NotificationParams(BaseModel): class Meta(BaseModel): model_config = ConfigDict(extra="allow") @@ -394,10 +408,11 @@ class ProgressNotification(Notification[ProgressNotificationParams, Literal["not params: ProgressNotificationParams -class ListResourcesRequest(PaginatedRequest[Literal["resources/list"]]): +class ListResourcesRequest(Request[ListResourcesRequestParams | None, Literal["resources/list"]]): """Sent from the client to request a list of resources the server has.""" method: Literal["resources/list"] + params: ListResourcesRequestParams | None = None class Annotations(BaseModel): @@ -461,10 +476,13 @@ class ListResourcesResult(PaginatedResult): resources: list[Resource] -class ListResourceTemplatesRequest(PaginatedRequest[Literal["resources/templates/list"]]): +class ListResourceTemplatesRequest( + Request[ListResourceTemplatesRequestParams | None, Literal["resources/templates/list"]] +): """Sent from the client to request a list of resource templates the server has.""" method: Literal["resources/templates/list"] + params: ListResourceTemplatesRequestParams | None = None class ListResourceTemplatesResult(PaginatedResult): diff --git a/tests/issues/test_152_resource_mime_type.py b/tests/issues/test_152_resource_mime_type.py index a99e5a5c7..6e9036174 100644 --- a/tests/issues/test_152_resource_mime_type.py +++ b/tests/issues/test_152_resource_mime_type.py @@ -79,7 +79,7 @@ async def test_lowlevel_resource_mime_type(): ] @server.list_resources() - async def handle_list_resources(): + async def handle_list_resources(request: types.ListResourcesRequest): return test_resources @server.read_resource() diff --git a/tests/server/fastmcp/resources/test_resource_manager.py b/tests/server/fastmcp/resources/test_resource_manager.py index 4423e5315..689b1f6ae 100644 --- a/tests/server/fastmcp/resources/test_resource_manager.py +++ b/tests/server/fastmcp/resources/test_resource_manager.py @@ -139,3 +139,97 @@ def test_list_resources(self, temp_file: Path): resources = manager.list_resources() assert len(resources) == 2 assert resources == [resource1, resource2] + + def test_list_resources_with_prefix(self, temp_file: Path): + """Test listing resources with prefix filtering.""" + manager = ResourceManager() + + # Add resources with different URIs + resource1 = FileResource( + uri=FileUrl("file:///data/images/test.jpg"), + name="test_image", + path=temp_file, + ) + resource2 = FileResource( + uri=FileUrl("file:///data/docs/test.txt"), + name="test_doc", + path=temp_file, + ) + resource3 = FileResource( + uri=FileUrl("file:///other/test.txt"), + name="other_test", + path=temp_file, + ) + + manager.add_resource(resource1) + manager.add_resource(resource2) + manager.add_resource(resource3) + + # Test prefix filtering + data_resources = manager.list_resources(prefix="file:///data/") + assert len(data_resources) == 2 + assert resource1 in data_resources + assert resource2 in data_resources + + # More specific prefix + image_resources = manager.list_resources(prefix="file:///data/images/") + assert len(image_resources) == 1 + assert resource1 in image_resources + + # No matches + no_matches = manager.list_resources(prefix="file:///nonexistent/") + assert len(no_matches) == 0 + + def test_list_templates_with_prefix(self): + """Test listing templates with prefix filtering.""" + manager = ResourceManager() + + # Add templates with different URI patterns + def user_func(user_id: str) -> str: + return f"User {user_id}" + + def post_func(user_id: str, post_id: str) -> str: + return f"User {user_id} Post {post_id}" + + def product_func(product_id: str) -> str: + return f"Product {product_id}" + + template1 = manager.add_template(user_func, uri_template="http://api.com/users/{user_id}", name="user_template") + template2 = manager.add_template( + post_func, uri_template="http://api.com/users/{user_id}/posts/{post_id}", name="post_template" + ) + template3 = manager.add_template( + product_func, uri_template="http://api.com/products/{product_id}", name="product_template" + ) + + # Test listing all templates + all_templates = manager.list_templates() + assert len(all_templates) == 3 + + # Test prefix filtering - matches both user templates + user_templates = manager.list_templates(prefix="http://api.com/users/") + assert len(user_templates) == 2 + assert template1 in user_templates + assert template2 in user_templates + + # Test partial materialization - only matches post template + # The template users/{user_id} generates "users/123" not "users/123/" + # But users/{user_id}/posts/{post_id} can generate "users/123/posts/456" + user_123_templates = manager.list_templates(prefix="http://api.com/users/123/") + assert len(user_123_templates) == 1 + assert template2 in user_123_templates # users/{user_id}/posts/{post_id} matches + + # Without trailing slash, both match + user_123_no_slash = manager.list_templates(prefix="http://api.com/users/123") + assert len(user_123_no_slash) == 2 + assert template1 in user_123_no_slash + assert template2 in user_123_no_slash + + # Test product prefix + product_templates = manager.list_templates(prefix="http://api.com/products/") + assert len(product_templates) == 1 + assert template3 in product_templates + + # No matches + no_matches = manager.list_templates(prefix="http://api.com/orders/") + assert len(no_matches) == 0 diff --git a/tests/server/fastmcp/resources/test_resource_template.py b/tests/server/fastmcp/resources/test_resource_template.py index f47244361..bcf040813 100644 --- a/tests/server/fastmcp/resources/test_resource_template.py +++ b/tests/server/fastmcp/resources/test_resource_template.py @@ -186,3 +186,117 @@ def get_data(value: str) -> CustomData: assert isinstance(resource, FunctionResource) content = await resource.read() assert content == '"hello"' + + def test_matches_prefix_exact_template(self): + """Test that templates match when prefix matches template exactly.""" + + def dummy_func() -> str: + return "data" + + template = ResourceTemplate.from_function( + dummy_func, uri_template="http://api.example.com/users/{user_id}", name="test" + ) + + # Exact prefix of template + assert template.matches_prefix("http://api.example.com/users/") + assert template.matches_prefix("http://api.example.com/users") + assert template.matches_prefix("http://api.example.com/") + assert template.matches_prefix("http://") + + def test_matches_prefix_partial_materialization(self): + """Test matching with partially materialized parameters.""" + + def dummy_func(user_id: str, post_id: str) -> str: + return f"User {user_id} Post {post_id}" + + template = ResourceTemplate.from_function( + dummy_func, uri_template="http://api.example.com/users/{user_id}/posts/{post_id}", name="test" + ) + + # Partial materialization - user_id replaced with value + assert template.matches_prefix("http://api.example.com/users/123/") + assert template.matches_prefix("http://api.example.com/users/123/posts/") + assert template.matches_prefix("http://api.example.com/users/alice/posts/") + + # Without trailing slash + assert template.matches_prefix("http://api.example.com/users/123") + assert template.matches_prefix("http://api.example.com/users/123/posts") + + def test_matches_prefix_no_match_different_structure(self): + """Test that templates don't match when structure differs.""" + + def dummy_func(user_id: str) -> str: + return f"User {user_id}" + + template = ResourceTemplate.from_function( + dummy_func, uri_template="http://api.example.com/users/{user_id}", name="test" + ) + + # Different path structure + assert not template.matches_prefix("http://api.example.com/products/") + assert not template.matches_prefix("http://api.example.com/users/123/invalid/") + assert not template.matches_prefix("http://different.com/users/") + + def test_matches_prefix_complex_nested(self): + """Test matching with complex nested templates.""" + + def dummy_func(org_id: str, team_id: str, user_id: str) -> str: + return f"Org {org_id} Team {team_id} User {user_id}" + + template = ResourceTemplate.from_function( + dummy_func, uri_template="http://api.example.com/orgs/{org_id}/teams/{team_id}/users/{user_id}", name="test" + ) + + # Various levels of partial materialization + assert template.matches_prefix("http://api.example.com/orgs/") + assert template.matches_prefix("http://api.example.com/orgs/acme/") + assert template.matches_prefix("http://api.example.com/orgs/acme/teams/") + assert template.matches_prefix("http://api.example.com/orgs/acme/teams/dev/") + assert template.matches_prefix("http://api.example.com/orgs/acme/teams/dev/users/") + + def test_matches_prefix_file_uri(self): + """Test matching with file:// URI templates.""" + + def dummy_func(category: str, filename: str) -> str: + return f"File {category}/{filename}" + + template = ResourceTemplate.from_function( + dummy_func, uri_template="file:///data/{category}/{filename}", name="test" + ) + + assert template.matches_prefix("file:///data/") + assert template.matches_prefix("file:///data/images/") + assert template.matches_prefix("file:///data/docs/") + assert not template.matches_prefix("file:///other/") + + def test_matches_prefix_trailing_slash_semantics(self): + """Test that trailing slashes have semantic meaning.""" + + def dummy_func(id: str) -> str: + return f"Item {id}" + + template = ResourceTemplate.from_function( + dummy_func, uri_template="http://api.example.com/items/{id}", name="test" + ) + + # Prefix without trailing slash matches (looking for items or under items) + assert template.matches_prefix("http://api.example.com/items") + assert template.matches_prefix("http://api.example.com/items/123") + + # Prefix with trailing slash only matches if template generates something under it + assert template.matches_prefix("http://api.example.com/items/") # template generates items/X + assert not template.matches_prefix("http://api.example.com/items/123/") # template can't generate items/123/... + + def test_matches_prefix_longer_than_template(self): + """Test that prefixes longer than template don't match.""" + + def dummy_func(id: str) -> str: + return f"Item {id}" + + template = ResourceTemplate.from_function( + dummy_func, uri_template="http://api.example.com/items/{id}", name="test" + ) + + # Prefix has more segments than template + assert not template.matches_prefix("http://api.example.com/items/123/extra/") + assert not template.matches_prefix("http://api.example.com/items/123/extra/more/") diff --git a/tests/server/test_session.py b/tests/server/test_session.py index 154c3a368..e10a51b4d 100644 --- a/tests/server/test_session.py +++ b/tests/server/test_session.py @@ -100,7 +100,7 @@ async def list_prompts(): # Add a resources handler @server.list_resources() - async def list_resources(): + async def list_resources(request: types.ListResourcesRequest): return [] caps = server.get_capabilities(notification_options, experimental_capabilities) diff --git a/tests/shared/test_memory.py b/tests/shared/test_memory.py index a0c32f556..b1e0c5c73 100644 --- a/tests/shared/test_memory.py +++ b/tests/shared/test_memory.py @@ -9,6 +9,7 @@ ) from mcp.types import ( EmptyResult, + ListResourcesRequest, Resource, ) @@ -18,7 +19,7 @@ def mcp_server() -> Server: server = Server(name="test_server") @server.list_resources() - async def handle_list_resources(): + async def handle_list_resources(request: ListResourcesRequest): return [ Resource( uri=AnyUrl("memory://test"), From 79c89d5fb02b8ed4e7a9d3df36bb1485e8f2f767 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Fri, 1 Aug 2025 14:09:23 -0700 Subject: [PATCH 02/15] feat: implement resource-based inheritance for tools and prompts Add ToolResource and PromptResource base classes that extend the Resource base class. Tool now inherits from ToolResource and Prompt inherits from PromptResource, establishing a proper inheritance hierarchy. Tools and prompts automatically generate URIs with their respective schemes (tool://name and prompt://name) when created. This allows them to be accessed through the ResourceManager using their URIs while maintaining full backward compatibility with existing code. The ResourceManager's list_resources() method filters out tool and prompt URIs by default to preserve the existing API behavior. Tools and prompts can still be accessed directly by their URIs when needed. Comprehensive tests verify the inheritance model works correctly and that all existing functionality remains intact. --- src/mcp/server/fastmcp/prompts/base.py | 29 +++- src/mcp/server/fastmcp/resources/__init__.py | 4 + .../fastmcp/resources/prompt_resource.py | 37 ++++ .../fastmcp/resources/resource_manager.py | 25 ++- .../server/fastmcp/resources/tool_resource.py | 37 ++++ src/mcp/server/fastmcp/tools/base.py | 29 +++- .../fastmcp/resources/test_inheritance.py | 158 ++++++++++++++++++ 7 files changed, 307 insertions(+), 12 deletions(-) create mode 100644 src/mcp/server/fastmcp/resources/prompt_resource.py create mode 100644 src/mcp/server/fastmcp/resources/tool_resource.py create mode 100644 tests/server/fastmcp/resources/test_inheritance.py diff --git a/src/mcp/server/fastmcp/prompts/base.py b/src/mcp/server/fastmcp/prompts/base.py index b45cfc917..7ba31970e 100644 --- a/src/mcp/server/fastmcp/prompts/base.py +++ b/src/mcp/server/fastmcp/prompts/base.py @@ -1,12 +1,14 @@ """Base classes for FastMCP prompts.""" import inspect +import json from collections.abc import Awaitable, Callable, Sequence from typing import Any, Literal import pydantic_core from pydantic import BaseModel, Field, TypeAdapter, validate_call +from mcp.server.fastmcp.resources import PromptResource from mcp.types import ContentBlock, TextContent @@ -54,12 +56,9 @@ class PromptArgument(BaseModel): required: bool = Field(default=False, description="Whether the argument is required") -class Prompt(BaseModel): +class Prompt(PromptResource): """A prompt template that can be rendered with parameters.""" - name: str = Field(description="Name of the prompt") - title: str | None = Field(None, description="Human-readable title of the prompt") - description: str | None = Field(None, description="Description of what the prompt does") arguments: list[PromptArgument] | None = Field(None, description="Arguments that can be passed to the prompt") fn: Callable[..., PromptResult | Awaitable[PromptResult]] = Field(exclude=True) @@ -111,6 +110,28 @@ def from_function( fn=fn, ) + async def read(self) -> str | bytes: + """Read the prompt template/documentation as JSON.""" + prompt_info: dict[str, Any] = { + "name": self.name, + "title": self.title, + "description": self.description, + "uri": str(self.uri), + } + + # Include arguments if available + if self.arguments: + prompt_info["arguments"] = [ + { + "name": arg.name, + "description": arg.description, + "required": arg.required, + } + for arg in self.arguments + ] + + return json.dumps(prompt_info, indent=2) + async def render(self, arguments: dict[str, Any] | None = None) -> list[Message]: """Render the prompt with arguments.""" # Validate required arguments diff --git a/src/mcp/server/fastmcp/resources/__init__.py b/src/mcp/server/fastmcp/resources/__init__.py index b5805fb34..a2ac82d28 100644 --- a/src/mcp/server/fastmcp/resources/__init__.py +++ b/src/mcp/server/fastmcp/resources/__init__.py @@ -1,6 +1,8 @@ from .base import Resource +from .prompt_resource import PromptResource from .resource_manager import ResourceManager from .templates import ResourceTemplate +from .tool_resource import ToolResource from .types import ( BinaryResource, DirectoryResource, @@ -20,4 +22,6 @@ "DirectoryResource", "ResourceTemplate", "ResourceManager", + "ToolResource", + "PromptResource", ] diff --git a/src/mcp/server/fastmcp/resources/prompt_resource.py b/src/mcp/server/fastmcp/resources/prompt_resource.py new file mode 100644 index 000000000..44b6ff630 --- /dev/null +++ b/src/mcp/server/fastmcp/resources/prompt_resource.py @@ -0,0 +1,37 @@ +"""Prompt resource base class.""" + +import json +from typing import Any + +from pydantic import AnyUrl, Field + +from mcp.server.fastmcp.resources.base import Resource + + +class PromptResource(Resource): + """Base class for prompts that are also resources.""" + + # Override mime_type default for prompts + mime_type: str = Field( + default="application/json", + description="MIME type of the resource content", + pattern=r"^[a-zA-Z0-9]+/[a-zA-Z0-9\-+.]+$", + ) + + def __init__(self, **data: Any): + # Auto-generate URI if not provided + if "uri" not in data and "name" in data: + data["uri"] = AnyUrl(f"prompt://{data['name']}") + super().__init__(**data) + + async def read(self) -> str | bytes: + """Read the prompt template/documentation as JSON.""" + # This will be overridden by the Prompt class + return json.dumps( + { + "name": self.name, + "title": self.title, + "description": self.description, + "uri": str(self.uri), + } + ) diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index 7cc62b034..9d412faa3 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -87,11 +87,30 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: raise ValueError(f"Unknown resource: {uri}") def list_resources(self, prefix: str | None = None) -> list[Resource]: - """List all registered resources, optionally filtered by URI prefix.""" - resources = list(self._resources.values()) + """List all registered resources, optionally filtered by URI prefix. + + Note: Tool and prompt resources (with tool:// and prompt:// URIs) are excluded + by default to maintain API compatibility. + """ + all_resources = list(self._resources.values()) + + # Filter out tool and prompt resources to maintain API compatibility + resources = [ + r for r in all_resources if not (str(r.uri).startswith("tool://") or str(r.uri).startswith("prompt://")) + ] + + # Apply prefix filter if provided if prefix: resources = [r for r in resources if str(r.uri).startswith(prefix)] - logger.debug("Listing resources", extra={"count": len(resources), "prefix": prefix}) + + logger.debug( + "Listing resources", + extra={ + "total_count": len(all_resources), + "filtered_count": len(resources), + "prefix": prefix + } + ) return resources def list_templates(self, prefix: str | None = None) -> list[ResourceTemplate]: diff --git a/src/mcp/server/fastmcp/resources/tool_resource.py b/src/mcp/server/fastmcp/resources/tool_resource.py new file mode 100644 index 000000000..775bb4a76 --- /dev/null +++ b/src/mcp/server/fastmcp/resources/tool_resource.py @@ -0,0 +1,37 @@ +"""Tool resource base class.""" + +import json +from typing import Any + +from pydantic import AnyUrl, Field + +from mcp.server.fastmcp.resources.base import Resource + + +class ToolResource(Resource): + """Base class for tools that are also resources.""" + + # Override mime_type default for tools + mime_type: str = Field( + default="application/json", + description="MIME type of the resource content", + pattern=r"^[a-zA-Z0-9]+/[a-zA-Z0-9\-+.]+$", + ) + + def __init__(self, **data: Any): + # Auto-generate URI if not provided + if "uri" not in data and "name" in data: + data["uri"] = AnyUrl(f"tool://{data['name']}") + super().__init__(**data) + + async def read(self) -> str | bytes: + """Read the tool schema/documentation as JSON.""" + # This will be overridden by the Tool class + return json.dumps( + { + "name": self.name, + "title": self.title, + "description": self.description, + "uri": str(self.uri), + } + ) diff --git a/src/mcp/server/fastmcp/tools/base.py b/src/mcp/server/fastmcp/tools/base.py index f50126081..d8db0df35 100644 --- a/src/mcp/server/fastmcp/tools/base.py +++ b/src/mcp/server/fastmcp/tools/base.py @@ -2,13 +2,15 @@ import functools import inspect +import json from collections.abc import Callable from functools import cached_property from typing import TYPE_CHECKING, Any, get_origin -from pydantic import BaseModel, Field +from pydantic import Field from mcp.server.fastmcp.exceptions import ToolError +from mcp.server.fastmcp.resources import ToolResource from mcp.server.fastmcp.utilities.func_metadata import FuncMetadata, func_metadata from mcp.types import ToolAnnotations @@ -18,13 +20,10 @@ from mcp.shared.context import LifespanContextT, RequestT -class Tool(BaseModel): +class Tool(ToolResource): """Internal tool registration info.""" fn: Callable[..., Any] = Field(exclude=True) - name: str = Field(description="Name of the tool") - title: str | None = Field(None, description="Human-readable title of the tool") - description: str = Field(description="Description of what the tool does") parameters: dict[str, Any] = Field(description="JSON schema for tool parameters") fn_metadata: FuncMetadata = Field( description="Metadata about the function including a pydantic model for tool arguments" @@ -87,6 +86,26 @@ def from_function( annotations=annotations, ) + async def read(self) -> str | bytes: + """Read the tool schema/documentation as JSON.""" + tool_info = { + "name": self.name, + "title": self.title, + "description": self.description, + "uri": str(self.uri), + "parameters": self.parameters, + } + + # Include output schema if available + if self.output_schema: + tool_info["output_schema"] = self.output_schema + + # Include annotations if available + if self.annotations: + tool_info["annotations"] = self.annotations.model_dump(exclude_none=True) + + return json.dumps(tool_info, indent=2) + async def run( self, arguments: dict[str, Any], diff --git a/tests/server/fastmcp/resources/test_inheritance.py b/tests/server/fastmcp/resources/test_inheritance.py new file mode 100644 index 000000000..bdfe0550f --- /dev/null +++ b/tests/server/fastmcp/resources/test_inheritance.py @@ -0,0 +1,158 @@ +"""Tests for resource inheritance model.""" + +import json + +import pytest + +from mcp.server.fastmcp.prompts import Prompt +from mcp.server.fastmcp.resources import ResourceManager +from mcp.server.fastmcp.tools import Tool +from mcp.types import ToolAnnotations + +pytestmark = pytest.mark.anyio + + +@pytest.fixture +def resource_manager(): + """Create a resource manager for testing.""" + return ResourceManager() + + +@pytest.fixture +def sample_tool(): + """Create a sample tool for testing.""" + + def add_numbers(a: int, b: int) -> int: + """Add two numbers together.""" + return a + b + + return Tool.from_function( + add_numbers, + name="add", + title="Add Numbers", + description="Adds two numbers together", + annotations=ToolAnnotations(), + ) + + +@pytest.fixture +def sample_prompt(): + """Create a sample prompt for testing.""" + + def greeting_prompt(name: str) -> str: + """Generate a greeting message.""" + return f"Hello, {name}!" + + return Prompt.from_function( + greeting_prompt, + name="greeting", + title="Greeting Prompt", + description="Generates a personalized greeting", + ) + + +class TestToolInheritance: + """Tests for Tool inheriting from Resource.""" + + def test_tool_is_resource(self, sample_tool): + """Test that Tool inherits from Resource.""" + # Tool should have URI automatically generated + assert str(sample_tool.uri) == "tool://add" + assert sample_tool.name == "add" + assert sample_tool.title == "Add Numbers" + assert sample_tool.description == "Adds two numbers together" + assert sample_tool.mime_type == "application/json" + + async def test_tool_read_method(self, sample_tool): + """Test reading tool schema via Resource interface.""" + content = await sample_tool.read() + + data = json.loads(content) + assert data["name"] == "add" + assert data["title"] == "Add Numbers" + assert data["description"] == "Adds two numbers together" + assert "parameters" in data + # Check that annotations are included (but empty in this case) + assert "annotations" in data + assert data["annotations"] == {} + + +class TestPromptInheritance: + """Tests for Prompt inheriting from Resource.""" + + def test_prompt_is_resource(self, sample_prompt): + """Test that Prompt inherits from Resource.""" + # Prompt should have URI automatically generated + assert str(sample_prompt.uri) == "prompt://greeting" + assert sample_prompt.name == "greeting" + assert sample_prompt.title == "Greeting Prompt" + assert sample_prompt.description == "Generates a personalized greeting" + assert sample_prompt.mime_type == "application/json" + + async def test_prompt_read_method(self, sample_prompt): + """Test reading prompt info via Resource interface.""" + content = await sample_prompt.read() + + data = json.loads(content) + assert data["name"] == "greeting" + assert data["title"] == "Greeting Prompt" + assert data["description"] == "Generates a personalized greeting" + assert len(data["arguments"]) == 1 + assert data["arguments"][0]["name"] == "name" + assert data["arguments"][0]["required"] is True + + +class TestResourceManagerIntegration: + """Tests for ResourceManager with inheritance model.""" + + async def test_tool_as_resource_lookup(self, resource_manager, sample_tool): + """Test that tools can be accessed as resources.""" + # Add tool directly - it's already a resource + resource_manager.add_resource(sample_tool) + + # Should be able to get it by URI + retrieved = await resource_manager.get_resource("tool://add") + assert retrieved is not None + assert isinstance(retrieved, Tool) + + # Read the content + content = await retrieved.read() + data = json.loads(content) + assert data["name"] == "add" + + async def test_prompt_as_resource_lookup(self, resource_manager, sample_prompt): + """Test that prompts can be accessed as resources.""" + # Add prompt directly - it's already a resource + resource_manager.add_resource(sample_prompt) + + # Should be able to get it by URI + retrieved = await resource_manager.get_resource("prompt://greeting") + assert retrieved is not None + assert isinstance(retrieved, Prompt) + + # Read the content + content = await retrieved.read() + data = json.loads(content) + assert data["name"] == "greeting" + + def test_list_resources_filters_tools_and_prompts(self, resource_manager, sample_tool, sample_prompt): + """Test that list_resources filters out tool/prompt resources.""" + from mcp.server.fastmcp.resources import TextResource + + # Add regular resource + from pydantic import AnyUrl + text_resource = TextResource(uri=AnyUrl("file://test.txt"), name="test.txt", text="Hello world") + resource_manager.add_resource(text_resource) + + # Add tool and prompt as resources + resource_manager.add_resource(sample_tool) + resource_manager.add_resource(sample_prompt) + + # List should only include the text resource + resources = resource_manager.list_resources() + assert len(resources) == 1 + assert resources[0].uri == text_resource.uri + + # But we can still access tools/prompts by URI + assert resource_manager._resources.get("tool://add") is not None + assert resource_manager._resources.get("prompt://greeting") is not None From a9e67fda0103ed32baed12ebfcedda23b627c202 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Fri, 1 Aug 2025 14:31:26 -0700 Subject: [PATCH 03/15] style: apply ruff formatting Apply automated formatting from ruff to ensure consistent code style across the combined features. --- .../server/fastmcp/resources/resource_manager.py | 16 ++++++---------- .../server/fastmcp/resources/test_inheritance.py | 5 +++-- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index 9d412faa3..6b0546291 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -88,28 +88,24 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: def list_resources(self, prefix: str | None = None) -> list[Resource]: """List all registered resources, optionally filtered by URI prefix. - + Note: Tool and prompt resources (with tool:// and prompt:// URIs) are excluded by default to maintain API compatibility. """ all_resources = list(self._resources.values()) - + # Filter out tool and prompt resources to maintain API compatibility resources = [ r for r in all_resources if not (str(r.uri).startswith("tool://") or str(r.uri).startswith("prompt://")) ] - + # Apply prefix filter if provided if prefix: resources = [r for r in resources if str(r.uri).startswith(prefix)] - + logger.debug( - "Listing resources", - extra={ - "total_count": len(all_resources), - "filtered_count": len(resources), - "prefix": prefix - } + "Listing resources", + extra={"total_count": len(all_resources), "filtered_count": len(resources), "prefix": prefix}, ) return resources diff --git a/tests/server/fastmcp/resources/test_inheritance.py b/tests/server/fastmcp/resources/test_inheritance.py index bdfe0550f..35570339b 100644 --- a/tests/server/fastmcp/resources/test_inheritance.py +++ b/tests/server/fastmcp/resources/test_inheritance.py @@ -137,10 +137,11 @@ async def test_prompt_as_resource_lookup(self, resource_manager, sample_prompt): def test_list_resources_filters_tools_and_prompts(self, resource_manager, sample_tool, sample_prompt): """Test that list_resources filters out tool/prompt resources.""" - from mcp.server.fastmcp.resources import TextResource - # Add regular resource from pydantic import AnyUrl + + from mcp.server.fastmcp.resources import TextResource + text_resource = TextResource(uri=AnyUrl("file://test.txt"), name="test.txt", text="Hello world") resource_manager.add_resource(text_resource) From a9635c3bf0c88fdbda01b87a61252a2f0c760e76 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Fri, 1 Aug 2025 15:40:24 -0700 Subject: [PATCH 04/15] feat: Convert tools and prompts to URI-based storage - Add uri field to FastMCP Tool and Prompt classes with automatic generation - Change ToolManager and PromptManager to use URIs as primary keys - Implement backward compatibility with automatic name-to-URI conversion - Update server to use stored URIs instead of generating them - Fix tests to handle URI-based warning messages This aligns tools and prompts with the resource storage pattern, where URIs are the primary identifiers. Names are automatically converted to URIs (e.g., 'my_tool' -> 'tool://my_tool') for backward compatibility. --- src/mcp/server/fastmcp/prompts/base.py | 36 ++-- .../server/fastmcp/prompts/prompt_manager.py | 19 ++- src/mcp/server/fastmcp/resources/__init__.py | 4 - .../fastmcp/resources/prompt_resource.py | 37 ---- .../fastmcp/resources/resource_manager.py | 21 +-- .../server/fastmcp/resources/tool_resource.py | 37 ---- src/mcp/server/fastmcp/server.py | 2 + src/mcp/server/fastmcp/tools/base.py | 36 ++-- src/mcp/server/fastmcp/tools/tool_manager.py | 23 ++- src/mcp/types.py | 14 +- .../fastmcp/resources/test_inheritance.py | 159 ------------------ tests/server/fastmcp/test_server.py | 5 + tests/server/fastmcp/test_title.py | 18 +- tests/server/fastmcp/test_tool_manager.py | 4 +- tests/test_types.py | 55 ++++++ 15 files changed, 143 insertions(+), 327 deletions(-) delete mode 100644 src/mcp/server/fastmcp/resources/prompt_resource.py delete mode 100644 src/mcp/server/fastmcp/resources/tool_resource.py delete mode 100644 tests/server/fastmcp/resources/test_inheritance.py diff --git a/src/mcp/server/fastmcp/prompts/base.py b/src/mcp/server/fastmcp/prompts/base.py index 7ba31970e..5117827de 100644 --- a/src/mcp/server/fastmcp/prompts/base.py +++ b/src/mcp/server/fastmcp/prompts/base.py @@ -1,14 +1,12 @@ """Base classes for FastMCP prompts.""" import inspect -import json from collections.abc import Awaitable, Callable, Sequence from typing import Any, Literal import pydantic_core from pydantic import BaseModel, Field, TypeAdapter, validate_call -from mcp.server.fastmcp.resources import PromptResource from mcp.types import ContentBlock, TextContent @@ -56,12 +54,22 @@ class PromptArgument(BaseModel): required: bool = Field(default=False, description="Whether the argument is required") -class Prompt(PromptResource): +class Prompt(BaseModel): """A prompt template that can be rendered with parameters.""" + name: str = Field(description="Name of the prompt") + uri: str = Field(description="URI of the prompt") + title: str | None = Field(None, description="Human-readable title of the prompt") + description: str = Field(description="Description of what the prompt does") arguments: list[PromptArgument] | None = Field(None, description="Arguments that can be passed to the prompt") fn: Callable[..., PromptResult | Awaitable[PromptResult]] = Field(exclude=True) + def __init__(self, **data: Any) -> None: + """Initialize Prompt, generating URI from name if not provided.""" + if "uri" not in data and "name" in data: + data["uri"] = f"prompt://{data['name']}" + super().__init__(**data) + @classmethod def from_function( cls, @@ -110,28 +118,6 @@ def from_function( fn=fn, ) - async def read(self) -> str | bytes: - """Read the prompt template/documentation as JSON.""" - prompt_info: dict[str, Any] = { - "name": self.name, - "title": self.title, - "description": self.description, - "uri": str(self.uri), - } - - # Include arguments if available - if self.arguments: - prompt_info["arguments"] = [ - { - "name": arg.name, - "description": arg.description, - "required": arg.required, - } - for arg in self.arguments - ] - - return json.dumps(prompt_info, indent=2) - async def render(self, arguments: dict[str, Any] | None = None) -> list[Message]: """Render the prompt with arguments.""" # Validate required arguments diff --git a/src/mcp/server/fastmcp/prompts/prompt_manager.py b/src/mcp/server/fastmcp/prompts/prompt_manager.py index 389e89624..7b909e1a0 100644 --- a/src/mcp/server/fastmcp/prompts/prompt_manager.py +++ b/src/mcp/server/fastmcp/prompts/prompt_manager.py @@ -13,20 +13,27 @@ def __init__(self, warn_on_duplicate_prompts: bool = True): self._prompts: dict[str, Prompt] = {} self.warn_on_duplicate_prompts = warn_on_duplicate_prompts + def _normalize_to_uri(self, name_or_uri: str) -> str: + """Convert name to URI if needed.""" + if name_or_uri.startswith("prompt://"): + return name_or_uri + return f"prompt://{name_or_uri}" + def add_prompt(self, prompt: Prompt) -> Prompt: """Add a prompt to the manager.""" - logger.debug(f"Adding prompt: {prompt.name}") - existing = self._prompts.get(prompt.name) + logger.debug(f"Adding prompt: {prompt.name} with URI: {prompt.uri}") + existing = self._prompts.get(prompt.uri) if existing: if self.warn_on_duplicate_prompts: - logger.warning(f"Prompt already exists: {prompt.name}") + logger.warning(f"Prompt already exists: {prompt.uri}") return existing - self._prompts[prompt.name] = prompt + self._prompts[prompt.uri] = prompt return prompt def get_prompt(self, name: str) -> Prompt | None: - """Get prompt by name.""" - return self._prompts.get(name) + """Get prompt by name or URI.""" + uri = self._normalize_to_uri(name) + return self._prompts.get(uri) def list_prompts(self) -> list[Prompt]: """List all registered prompts.""" diff --git a/src/mcp/server/fastmcp/resources/__init__.py b/src/mcp/server/fastmcp/resources/__init__.py index a2ac82d28..b5805fb34 100644 --- a/src/mcp/server/fastmcp/resources/__init__.py +++ b/src/mcp/server/fastmcp/resources/__init__.py @@ -1,8 +1,6 @@ from .base import Resource -from .prompt_resource import PromptResource from .resource_manager import ResourceManager from .templates import ResourceTemplate -from .tool_resource import ToolResource from .types import ( BinaryResource, DirectoryResource, @@ -22,6 +20,4 @@ "DirectoryResource", "ResourceTemplate", "ResourceManager", - "ToolResource", - "PromptResource", ] diff --git a/src/mcp/server/fastmcp/resources/prompt_resource.py b/src/mcp/server/fastmcp/resources/prompt_resource.py deleted file mode 100644 index 44b6ff630..000000000 --- a/src/mcp/server/fastmcp/resources/prompt_resource.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Prompt resource base class.""" - -import json -from typing import Any - -from pydantic import AnyUrl, Field - -from mcp.server.fastmcp.resources.base import Resource - - -class PromptResource(Resource): - """Base class for prompts that are also resources.""" - - # Override mime_type default for prompts - mime_type: str = Field( - default="application/json", - description="MIME type of the resource content", - pattern=r"^[a-zA-Z0-9]+/[a-zA-Z0-9\-+.]+$", - ) - - def __init__(self, **data: Any): - # Auto-generate URI if not provided - if "uri" not in data and "name" in data: - data["uri"] = AnyUrl(f"prompt://{data['name']}") - super().__init__(**data) - - async def read(self) -> str | bytes: - """Read the prompt template/documentation as JSON.""" - # This will be overridden by the Prompt class - return json.dumps( - { - "name": self.name, - "title": self.title, - "description": self.description, - "uri": str(self.uri), - } - ) diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index 6b0546291..7cc62b034 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -87,26 +87,11 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: raise ValueError(f"Unknown resource: {uri}") def list_resources(self, prefix: str | None = None) -> list[Resource]: - """List all registered resources, optionally filtered by URI prefix. - - Note: Tool and prompt resources (with tool:// and prompt:// URIs) are excluded - by default to maintain API compatibility. - """ - all_resources = list(self._resources.values()) - - # Filter out tool and prompt resources to maintain API compatibility - resources = [ - r for r in all_resources if not (str(r.uri).startswith("tool://") or str(r.uri).startswith("prompt://")) - ] - - # Apply prefix filter if provided + """List all registered resources, optionally filtered by URI prefix.""" + resources = list(self._resources.values()) if prefix: resources = [r for r in resources if str(r.uri).startswith(prefix)] - - logger.debug( - "Listing resources", - extra={"total_count": len(all_resources), "filtered_count": len(resources), "prefix": prefix}, - ) + logger.debug("Listing resources", extra={"count": len(resources), "prefix": prefix}) return resources def list_templates(self, prefix: str | None = None) -> list[ResourceTemplate]: diff --git a/src/mcp/server/fastmcp/resources/tool_resource.py b/src/mcp/server/fastmcp/resources/tool_resource.py deleted file mode 100644 index 775bb4a76..000000000 --- a/src/mcp/server/fastmcp/resources/tool_resource.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Tool resource base class.""" - -import json -from typing import Any - -from pydantic import AnyUrl, Field - -from mcp.server.fastmcp.resources.base import Resource - - -class ToolResource(Resource): - """Base class for tools that are also resources.""" - - # Override mime_type default for tools - mime_type: str = Field( - default="application/json", - description="MIME type of the resource content", - pattern=r"^[a-zA-Z0-9]+/[a-zA-Z0-9\-+.]+$", - ) - - def __init__(self, **data: Any): - # Auto-generate URI if not provided - if "uri" not in data and "name" in data: - data["uri"] = AnyUrl(f"tool://{data['name']}") - super().__init__(**data) - - async def read(self) -> str | bytes: - """Read the tool schema/documentation as JSON.""" - # This will be overridden by the Tool class - return json.dumps( - { - "name": self.name, - "title": self.title, - "description": self.description, - "uri": str(self.uri), - } - ) diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index aba2bcf0c..c59fd1c2d 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -275,6 +275,7 @@ async def list_tools(self) -> list[MCPTool]: name=info.name, title=info.title, description=info.description, + uri=info.uri, inputSchema=info.parameters, outputSchema=info.output_schema, annotations=info.annotations, @@ -973,6 +974,7 @@ async def list_prompts(self) -> list[MCPPrompt]: name=prompt.name, title=prompt.title, description=prompt.description, + uri=prompt.uri, arguments=[ MCPPromptArgument( name=arg.name, diff --git a/src/mcp/server/fastmcp/tools/base.py b/src/mcp/server/fastmcp/tools/base.py index d8db0df35..995045770 100644 --- a/src/mcp/server/fastmcp/tools/base.py +++ b/src/mcp/server/fastmcp/tools/base.py @@ -2,15 +2,13 @@ import functools import inspect -import json from collections.abc import Callable from functools import cached_property from typing import TYPE_CHECKING, Any, get_origin -from pydantic import Field +from pydantic import BaseModel, Field from mcp.server.fastmcp.exceptions import ToolError -from mcp.server.fastmcp.resources import ToolResource from mcp.server.fastmcp.utilities.func_metadata import FuncMetadata, func_metadata from mcp.types import ToolAnnotations @@ -20,9 +18,13 @@ from mcp.shared.context import LifespanContextT, RequestT -class Tool(ToolResource): +class Tool(BaseModel): """Internal tool registration info.""" + name: str = Field(description="Name of the tool") + uri: str = Field(description="URI of the tool") + title: str | None = Field(None, description="Human-readable title of the tool") + description: str = Field(description="Description of what the tool does") fn: Callable[..., Any] = Field(exclude=True) parameters: dict[str, Any] = Field(description="JSON schema for tool parameters") fn_metadata: FuncMetadata = Field( @@ -32,6 +34,12 @@ class Tool(ToolResource): context_kwarg: str | None = Field(None, description="Name of the kwarg that should receive context") annotations: ToolAnnotations | None = Field(None, description="Optional annotations for the tool") + def __init__(self, **data: Any) -> None: + """Initialize Tool, generating URI from name if not provided.""" + if "uri" not in data and "name" in data: + data["uri"] = f"tool://{data['name']}" + super().__init__(**data) + @cached_property def output_schema(self) -> dict[str, Any] | None: return self.fn_metadata.output_schema @@ -86,26 +94,6 @@ def from_function( annotations=annotations, ) - async def read(self) -> str | bytes: - """Read the tool schema/documentation as JSON.""" - tool_info = { - "name": self.name, - "title": self.title, - "description": self.description, - "uri": str(self.uri), - "parameters": self.parameters, - } - - # Include output schema if available - if self.output_schema: - tool_info["output_schema"] = self.output_schema - - # Include annotations if available - if self.annotations: - tool_info["annotations"] = self.annotations.model_dump(exclude_none=True) - - return json.dumps(tool_info, indent=2) - async def run( self, arguments: dict[str, Any], diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index bfa8b2382..cb6a7809f 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -28,15 +28,22 @@ def __init__( self._tools: dict[str, Tool] = {} if tools is not None: for tool in tools: - if warn_on_duplicate_tools and tool.name in self._tools: - logger.warning(f"Tool already exists: {tool.name}") - self._tools[tool.name] = tool + if warn_on_duplicate_tools and tool.uri in self._tools: + logger.warning(f"Tool already exists: {tool.uri}") + self._tools[tool.uri] = tool self.warn_on_duplicate_tools = warn_on_duplicate_tools + def _normalize_to_uri(self, name_or_uri: str) -> str: + """Convert name to URI if needed.""" + if name_or_uri.startswith("tool://"): + return name_or_uri + return f"tool://{name_or_uri}" + def get_tool(self, name: str) -> Tool | None: - """Get tool by name.""" - return self._tools.get(name) + """Get tool by name or URI.""" + uri = self._normalize_to_uri(name) + return self._tools.get(uri) def list_tools(self) -> list[Tool]: """List all registered tools.""" @@ -60,12 +67,12 @@ def add_tool( annotations=annotations, structured_output=structured_output, ) - existing = self._tools.get(tool.name) + existing = self._tools.get(tool.uri) if existing: if self.warn_on_duplicate_tools: - logger.warning(f"Tool already exists: {tool.name}") + logger.warning(f"Tool already exists: {tool.uri}") return existing - self._tools[tool.name] = tool + self._tools[tool.uri] = tool return tool async def call_tool( diff --git a/src/mcp/types.py b/src/mcp/types.py index 078bbc871..0338eac27 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -1,7 +1,7 @@ from collections.abc import Callable from typing import Annotated, Any, Generic, Literal, TypeAlias, TypeVar -from pydantic import BaseModel, ConfigDict, Field, FileUrl, RootModel +from pydantic import BaseModel, ConfigDict, Field, FileUrl, RootModel, model_validator from pydantic.networks import AnyUrl, UrlConstraints from typing_extensions import deprecated @@ -445,6 +445,14 @@ class Resource(BaseMetadata): """ model_config = ConfigDict(extra="allow") + @model_validator(mode="after") + def validate_uri_scheme(self) -> "Resource": + """Ensure resource URI doesn't use reserved schemes.""" + uri_str = str(self.uri) + if uri_str.startswith(("tool://", "prompt://")): + raise ValueError(f"Resource URI cannot use reserved schemes 'tool://' or 'prompt://', got: {self.uri}") + return self + class ResourceTemplate(BaseMetadata): """A template description for resources available on the server.""" @@ -642,6 +650,8 @@ class PromptArgument(BaseModel): class Prompt(BaseMetadata): """A prompt or prompt template that the server offers.""" + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=["prompt"], host_required=False)] + """URI for the prompt. Must use 'prompt' scheme.""" description: str | None = None """An optional description of what this prompt provides.""" arguments: list[PromptArgument] | None = None @@ -861,6 +871,8 @@ class ToolAnnotations(BaseModel): class Tool(BaseMetadata): """Definition for a tool the client can call.""" + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=["tool"], host_required=False)] + """URI for the tool. Must use 'tool' scheme.""" description: str | None = None """A human-readable description of the tool.""" inputSchema: dict[str, Any] diff --git a/tests/server/fastmcp/resources/test_inheritance.py b/tests/server/fastmcp/resources/test_inheritance.py deleted file mode 100644 index 35570339b..000000000 --- a/tests/server/fastmcp/resources/test_inheritance.py +++ /dev/null @@ -1,159 +0,0 @@ -"""Tests for resource inheritance model.""" - -import json - -import pytest - -from mcp.server.fastmcp.prompts import Prompt -from mcp.server.fastmcp.resources import ResourceManager -from mcp.server.fastmcp.tools import Tool -from mcp.types import ToolAnnotations - -pytestmark = pytest.mark.anyio - - -@pytest.fixture -def resource_manager(): - """Create a resource manager for testing.""" - return ResourceManager() - - -@pytest.fixture -def sample_tool(): - """Create a sample tool for testing.""" - - def add_numbers(a: int, b: int) -> int: - """Add two numbers together.""" - return a + b - - return Tool.from_function( - add_numbers, - name="add", - title="Add Numbers", - description="Adds two numbers together", - annotations=ToolAnnotations(), - ) - - -@pytest.fixture -def sample_prompt(): - """Create a sample prompt for testing.""" - - def greeting_prompt(name: str) -> str: - """Generate a greeting message.""" - return f"Hello, {name}!" - - return Prompt.from_function( - greeting_prompt, - name="greeting", - title="Greeting Prompt", - description="Generates a personalized greeting", - ) - - -class TestToolInheritance: - """Tests for Tool inheriting from Resource.""" - - def test_tool_is_resource(self, sample_tool): - """Test that Tool inherits from Resource.""" - # Tool should have URI automatically generated - assert str(sample_tool.uri) == "tool://add" - assert sample_tool.name == "add" - assert sample_tool.title == "Add Numbers" - assert sample_tool.description == "Adds two numbers together" - assert sample_tool.mime_type == "application/json" - - async def test_tool_read_method(self, sample_tool): - """Test reading tool schema via Resource interface.""" - content = await sample_tool.read() - - data = json.loads(content) - assert data["name"] == "add" - assert data["title"] == "Add Numbers" - assert data["description"] == "Adds two numbers together" - assert "parameters" in data - # Check that annotations are included (but empty in this case) - assert "annotations" in data - assert data["annotations"] == {} - - -class TestPromptInheritance: - """Tests for Prompt inheriting from Resource.""" - - def test_prompt_is_resource(self, sample_prompt): - """Test that Prompt inherits from Resource.""" - # Prompt should have URI automatically generated - assert str(sample_prompt.uri) == "prompt://greeting" - assert sample_prompt.name == "greeting" - assert sample_prompt.title == "Greeting Prompt" - assert sample_prompt.description == "Generates a personalized greeting" - assert sample_prompt.mime_type == "application/json" - - async def test_prompt_read_method(self, sample_prompt): - """Test reading prompt info via Resource interface.""" - content = await sample_prompt.read() - - data = json.loads(content) - assert data["name"] == "greeting" - assert data["title"] == "Greeting Prompt" - assert data["description"] == "Generates a personalized greeting" - assert len(data["arguments"]) == 1 - assert data["arguments"][0]["name"] == "name" - assert data["arguments"][0]["required"] is True - - -class TestResourceManagerIntegration: - """Tests for ResourceManager with inheritance model.""" - - async def test_tool_as_resource_lookup(self, resource_manager, sample_tool): - """Test that tools can be accessed as resources.""" - # Add tool directly - it's already a resource - resource_manager.add_resource(sample_tool) - - # Should be able to get it by URI - retrieved = await resource_manager.get_resource("tool://add") - assert retrieved is not None - assert isinstance(retrieved, Tool) - - # Read the content - content = await retrieved.read() - data = json.loads(content) - assert data["name"] == "add" - - async def test_prompt_as_resource_lookup(self, resource_manager, sample_prompt): - """Test that prompts can be accessed as resources.""" - # Add prompt directly - it's already a resource - resource_manager.add_resource(sample_prompt) - - # Should be able to get it by URI - retrieved = await resource_manager.get_resource("prompt://greeting") - assert retrieved is not None - assert isinstance(retrieved, Prompt) - - # Read the content - content = await retrieved.read() - data = json.loads(content) - assert data["name"] == "greeting" - - def test_list_resources_filters_tools_and_prompts(self, resource_manager, sample_tool, sample_prompt): - """Test that list_resources filters out tool/prompt resources.""" - # Add regular resource - from pydantic import AnyUrl - - from mcp.server.fastmcp.resources import TextResource - - text_resource = TextResource(uri=AnyUrl("file://test.txt"), name="test.txt", text="Hello world") - resource_manager.add_resource(text_resource) - - # Add tool and prompt as resources - resource_manager.add_resource(sample_tool) - resource_manager.add_resource(sample_prompt) - - # List should only include the text resource - resources = resource_manager.list_resources() - assert len(resources) == 1 - assert resources[0].uri == text_resource.uri - - # But we can still access tools/prompts by URI - assert resource_manager._resources.get("tool://add") is not None - assert resource_manager._resources.get("prompt://greeting") is not None diff --git a/tests/server/fastmcp/test_server.py b/tests/server/fastmcp/test_server.py index a9e0d182a..d9afc6d98 100644 --- a/tests/server/fastmcp/test_server.py +++ b/tests/server/fastmcp/test_server.py @@ -217,6 +217,9 @@ async def test_list_tools(self): async with client_session(mcp._mcp_server) as client: tools = await client.list_tools() assert len(tools.tools) == 1 + # Verify URI is generated + tool = tools.tools[0] + assert str(tool.uri) == "tool://tool_fn" @pytest.mark.anyio async def test_call_tool(self): @@ -957,6 +960,8 @@ def fn(name: str, optional: str = "default") -> str: assert len(result.prompts) == 1 prompt = result.prompts[0] assert prompt.name == "fn" + # Verify URI is generated + assert str(prompt.uri) == "prompt://fn" assert prompt.arguments is not None assert len(prompt.arguments) == 2 assert prompt.arguments[0].name == "name" diff --git a/tests/server/fastmcp/test_title.py b/tests/server/fastmcp/test_title.py index a94f6671d..976565c05 100644 --- a/tests/server/fastmcp/test_title.py +++ b/tests/server/fastmcp/test_title.py @@ -181,17 +181,23 @@ async def test_get_display_name_utility(): """Test the get_display_name utility function.""" # Test tool precedence: title > annotations.title > name - tool_name_only = Tool(name="test_tool", inputSchema={}) + tool_name_only = Tool(name="test_tool", uri="tool://test_tool", inputSchema={}) assert get_display_name(tool_name_only) == "test_tool" - tool_with_title = Tool(name="test_tool", title="Test Tool", inputSchema={}) + tool_with_title = Tool(name="test_tool", uri="tool://test_tool", title="Test Tool", inputSchema={}) assert get_display_name(tool_with_title) == "Test Tool" - tool_with_annotations = Tool(name="test_tool", inputSchema={}, annotations=ToolAnnotations(title="Annotated Tool")) + tool_with_annotations = Tool( + name="test_tool", uri="tool://test_tool", inputSchema={}, annotations=ToolAnnotations(title="Annotated Tool") + ) assert get_display_name(tool_with_annotations) == "Annotated Tool" tool_with_both = Tool( - name="test_tool", title="Primary Title", inputSchema={}, annotations=ToolAnnotations(title="Secondary Title") + name="test_tool", + uri="tool://test_tool", + title="Primary Title", + inputSchema={}, + annotations=ToolAnnotations(title="Secondary Title"), ) assert get_display_name(tool_with_both) == "Primary Title" @@ -202,10 +208,10 @@ async def test_get_display_name_utility(): resource_with_title = Resource(uri=AnyUrl("file://test"), name="test_res", title="Test Resource") assert get_display_name(resource_with_title) == "Test Resource" - prompt = Prompt(name="test_prompt") + prompt = Prompt(name="test_prompt", uri="prompt://test_prompt") assert get_display_name(prompt) == "test_prompt" - prompt_with_title = Prompt(name="test_prompt", title="Test Prompt") + prompt_with_title = Prompt(name="test_prompt", uri="prompt://test_prompt", title="Test Prompt") assert get_display_name(prompt_with_title) == "Test Prompt" template = ResourceTemplate(uriTemplate="file://{id}", name="test_template") diff --git a/tests/server/fastmcp/test_tool_manager.py b/tests/server/fastmcp/test_tool_manager.py index 27e16cc8e..f357fe761 100644 --- a/tests/server/fastmcp/test_tool_manager.py +++ b/tests/server/fastmcp/test_tool_manager.py @@ -62,7 +62,7 @@ class AddArguments(ArgModelBase): # warn on duplicate tools with caplog.at_level(logging.WARNING): manager = ToolManager(True, tools=[original_tool, original_tool]) - assert "Tool already exists: sum" in caplog.text + assert "Tool already exists: tool://sum" in caplog.text @pytest.mark.anyio async def test_async_function(self): @@ -163,7 +163,7 @@ def f(x: int) -> int: manager.add_tool(f) with caplog.at_level(logging.WARNING): manager.add_tool(f) - assert "Tool already exists: f" in caplog.text + assert "Tool already exists: tool://f" in caplog.text def test_disable_warn_on_duplicate_tools(self, caplog): """Test disabling warning on duplicate tools.""" diff --git a/tests/test_types.py b/tests/test_types.py index a39d33412..5366ec4dc 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -3,8 +3,12 @@ from mcp.types import ( LATEST_PROTOCOL_VERSION, ClientRequest, + Implementation, JSONRPCMessage, JSONRPCRequest, + Prompt, + Resource, + Tool, ) @@ -30,3 +34,54 @@ async def test_jsonrpc_request(): assert request.root.method == "initialize" assert request.root.params is not None assert request.root.params["protocolVersion"] == LATEST_PROTOCOL_VERSION + + +def test_implementation_no_uri(): + """Test that Implementation doesn't have URI field.""" + impl = Implementation(name="test-server", version="1.0.0") + assert impl.name == "test-server" + assert impl.version == "1.0.0" + assert not hasattr(impl, "uri") + + +def test_resource_uri(): + """Test that Resource requires URI and validates scheme.""" + # Resource should require URI + with pytest.raises(ValueError): + Resource(name="test") + + # This should work + resource = Resource(name="test", uri="file://test.txt") + assert resource.name == "test" + assert str(resource.uri) == "file://test.txt/" # AnyUrl adds trailing slash + + # Should reject tool:// and prompt:// schemes + with pytest.raises(ValueError, match="reserved schemes"): + Resource(name="test", uri="tool://test") + + with pytest.raises(ValueError, match="reserved schemes"): + Resource(name="test", uri="prompt://test") + + +def test_tool_uri_validation(): + """Test that Tool requires URI with tool scheme.""" + # Tool requires URI with tool:// scheme + tool = Tool(name="calculator", inputSchema={"type": "object"}, uri="tool://calculator") + assert tool.name == "calculator" + assert str(tool.uri) == "tool://calculator" + + # Should reject non-tool schemes + with pytest.raises(ValueError): + Tool(name="calculator", inputSchema={"type": "object"}, uri="custom://calc") + + +def test_prompt_uri_validation(): + """Test that Prompt requires URI with prompt scheme.""" + # Prompt requires URI with prompt:// scheme + prompt = Prompt(name="greeting", uri="prompt://greeting") + assert prompt.name == "greeting" + assert str(prompt.uri) == "prompt://greeting" + + # Should reject non-prompt schemes + with pytest.raises(ValueError): + Prompt(name="greeting", uri="custom://greet") From 777b67020098ffbeee59048ac54b9cf608c0d781 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Fri, 1 Aug 2025 16:13:28 -0700 Subject: [PATCH 05/15] feat: Implement consistent prefix-based filtering for all list operations - Rename PaginatedRequestParams to ListRequestParams and add prefix field - Rename PaginatedRequest to ListRequest for semantic clarity - Rename PaginatedResult to ListResult for consistency - Remove redundant ListResourcesRequestParams and ListResourceTemplatesRequestParams - Add prefix filtering to tools and prompts list operations - Ensure all prefixes are treated as path prefixes ending with / - Update lowlevel server handlers to accept full request objects - Update FastMCP server to extract prefix from request params This unifies the list operation API across resources, templates, tools, and prompts. All list methods now support optional prefix filtering using URI path prefixes (e.g., 'tool://category/' to match only tools under that path). --- src/mcp/client/session.py | 4 +- .../server/fastmcp/prompts/prompt_manager.py | 13 +++-- .../fastmcp/resources/resource_manager.py | 6 +++ src/mcp/server/fastmcp/server.py | 18 ++++--- src/mcp/server/fastmcp/tools/tool_manager.py | 13 +++-- src/mcp/server/lowlevel/server.py | 12 ++--- src/mcp/types.py | 49 +++++++------------ 7 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/mcp/client/session.py b/src/mcp/client/session.py index 0c69436bf..91c7152ac 100644 --- a/src/mcp/client/session.py +++ b/src/mcp/client/session.py @@ -348,7 +348,7 @@ async def list_prompts(self, cursor: str | None = None) -> types.ListPromptsResu types.ClientRequest( types.ListPromptsRequest( method="prompts/list", - params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None, + params=types.ListRequestParams(cursor=cursor) if cursor is not None else None, ) ), types.ListPromptsResult, @@ -397,7 +397,7 @@ async def list_tools(self, cursor: str | None = None) -> types.ListToolsResult: types.ClientRequest( types.ListToolsRequest( method="tools/list", - params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None, + params=types.ListRequestParams(cursor=cursor) if cursor is not None else None, ) ), types.ListToolsResult, diff --git a/src/mcp/server/fastmcp/prompts/prompt_manager.py b/src/mcp/server/fastmcp/prompts/prompt_manager.py index 7b909e1a0..c8e221205 100644 --- a/src/mcp/server/fastmcp/prompts/prompt_manager.py +++ b/src/mcp/server/fastmcp/prompts/prompt_manager.py @@ -35,6 +35,13 @@ def get_prompt(self, name: str) -> Prompt | None: uri = self._normalize_to_uri(name) return self._prompts.get(uri) - def list_prompts(self) -> list[Prompt]: - """List all registered prompts.""" - return list(self._prompts.values()) + def list_prompts(self, prefix: str | None = None) -> list[Prompt]: + """List all registered prompts, optionally filtered by URI prefix.""" + prompts = list(self._prompts.values()) + if prefix: + # Ensure prefix ends with / for proper path matching + if not prefix.endswith("/"): + prefix = prefix + "/" + prompts = [p for p in prompts if str(p.uri).startswith(prefix)] + logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) + return prompts diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index 7cc62b034..ed11c0536 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -90,6 +90,9 @@ def list_resources(self, prefix: str | None = None) -> list[Resource]: """List all registered resources, optionally filtered by URI prefix.""" resources = list(self._resources.values()) if prefix: + # Ensure prefix ends with / for proper path matching + if not prefix.endswith("/"): + prefix = prefix + "/" resources = [r for r in resources if str(r.uri).startswith(prefix)] logger.debug("Listing resources", extra={"count": len(resources), "prefix": prefix}) return resources @@ -98,6 +101,9 @@ def list_templates(self, prefix: str | None = None) -> list[ResourceTemplate]: """List all registered templates, optionally filtered by URI template prefix.""" templates = list(self._templates.values()) if prefix: + # Ensure prefix ends with / for proper path matching + if not prefix.endswith("/"): + prefix = prefix + "/" templates = [t for t in templates if t.matches_prefix(prefix)] logger.debug("Listing templates", extra={"count": len(templates), "prefix": prefix}) return templates diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index c59fd1c2d..a2010e2cd 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -267,9 +267,12 @@ def _setup_handlers(self) -> None: self._mcp_server.get_prompt()(self.get_prompt) self._mcp_server.list_resource_templates()(self.list_resource_templates) - async def list_tools(self) -> list[MCPTool]: - """List all available tools.""" - tools = self._tool_manager.list_tools() + async def list_tools(self, request: types.ListToolsRequest) -> list[MCPTool]: + """List all available tools, optionally filtered by prefix.""" + prefix = None + if request.params: + prefix = request.params.prefix + tools = self._tool_manager.list_tools(prefix=prefix) return [ MCPTool( name=info.name, @@ -966,9 +969,12 @@ def streamable_http_app(self) -> Starlette: lifespan=lambda app: self.session_manager.run(), ) - async def list_prompts(self) -> list[MCPPrompt]: - """List all available prompts.""" - prompts = self._prompt_manager.list_prompts() + async def list_prompts(self, request: types.ListPromptsRequest) -> list[MCPPrompt]: + """List all available prompts, optionally filtered by prefix.""" + prefix = None + if request.params: + prefix = request.params.prefix + prompts = self._prompt_manager.list_prompts(prefix=prefix) return [ MCPPrompt( name=prompt.name, diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index cb6a7809f..bc8ec4948 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -45,9 +45,16 @@ def get_tool(self, name: str) -> Tool | None: uri = self._normalize_to_uri(name) return self._tools.get(uri) - def list_tools(self) -> list[Tool]: - """List all registered tools.""" - return list(self._tools.values()) + def list_tools(self, prefix: str | None = None) -> list[Tool]: + """List all registered tools, optionally filtered by URI prefix.""" + tools = list(self._tools.values()) + if prefix: + # Ensure prefix ends with / for proper path matching + if not prefix.endswith("/"): + prefix = prefix + "/" + tools = [t for t in tools if str(t.uri).startswith(prefix)] + logger.debug("Listing tools", extra={"count": len(tools), "prefix": prefix}) + return tools def add_tool( self, diff --git a/src/mcp/server/lowlevel/server.py b/src/mcp/server/lowlevel/server.py index 0100cdb50..0eadb5031 100644 --- a/src/mcp/server/lowlevel/server.py +++ b/src/mcp/server/lowlevel/server.py @@ -231,11 +231,11 @@ def request_context( return request_ctx.get() def list_prompts(self): - def decorator(func: Callable[[], Awaitable[list[types.Prompt]]]): + def decorator(func: Callable[[types.ListPromptsRequest], Awaitable[list[types.Prompt]]]): logger.debug("Registering handler for PromptListRequest") - async def handler(_: Any): - prompts = await func() + async def handler(request: types.ListPromptsRequest): + prompts = await func(request) return types.ServerResult(types.ListPromptsResult(prompts=prompts)) self.request_handlers[types.ListPromptsRequest] = handler @@ -382,11 +382,11 @@ async def handler(req: types.UnsubscribeRequest): return decorator def list_tools(self): - def decorator(func: Callable[[], Awaitable[list[types.Tool]]]): + def decorator(func: Callable[[types.ListToolsRequest], Awaitable[list[types.Tool]]]): logger.debug("Registering handler for ListToolsRequest") - async def handler(_: Any): - tools = await func() + async def handler(request: types.ListToolsRequest): + tools = await func(request) # Refresh the tool cache self._tool_cache.clear() for tool in tools: diff --git a/src/mcp/types.py b/src/mcp/types.py index 0338eac27..9c65fc31d 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -55,7 +55,10 @@ class Meta(BaseModel): meta: Meta | None = Field(alias="_meta", default=None) -class PaginatedRequestParams(RequestParams): +class ListRequestParams(RequestParams): + prefix: str | None = None + """Optional prefix to filter results by URI.""" + cursor: Cursor | None = None """ An opaque token representing the current pagination position. @@ -63,20 +66,6 @@ class PaginatedRequestParams(RequestParams): """ -class ListResourcesRequestParams(PaginatedRequestParams): - """Parameters for listing resources with optional prefix filtering.""" - - prefix: str | None = None - """Optional prefix to filter resources by URI.""" - - -class ListResourceTemplatesRequestParams(PaginatedRequestParams): - """Parameters for listing resource templates with optional prefix filtering.""" - - prefix: str | None = None - """Optional prefix to filter resource templates by URI template.""" - - class NotificationParams(BaseModel): class Meta(BaseModel): model_config = ConfigDict(extra="allow") @@ -101,11 +90,11 @@ class Request(BaseModel, Generic[RequestParamsT, MethodT]): model_config = ConfigDict(extra="allow") -class PaginatedRequest(Request[PaginatedRequestParams | None, MethodT], Generic[MethodT]): - """Base class for paginated requests, - matching the schema's PaginatedRequest interface.""" +class ListRequest(Request[ListRequestParams | None, MethodT], Generic[MethodT]): + """Base class for list requests, + matching the schema's ListRequest interface.""" - params: PaginatedRequestParams | None = None + params: ListRequestParams | None = None class Notification(BaseModel, Generic[NotificationParamsT, MethodT]): @@ -127,7 +116,7 @@ class Result(BaseModel): model_config = ConfigDict(extra="allow") -class PaginatedResult(Result): +class ListResult(Result): nextCursor: Cursor | None = None """ An opaque token representing the pagination position after the last returned result. @@ -408,11 +397,10 @@ class ProgressNotification(Notification[ProgressNotificationParams, Literal["not params: ProgressNotificationParams -class ListResourcesRequest(Request[ListResourcesRequestParams | None, Literal["resources/list"]]): +class ListResourcesRequest(ListRequest[Literal["resources/list"]]): """Sent from the client to request a list of resources the server has.""" method: Literal["resources/list"] - params: ListResourcesRequestParams | None = None class Annotations(BaseModel): @@ -478,22 +466,19 @@ class ResourceTemplate(BaseMetadata): model_config = ConfigDict(extra="allow") -class ListResourcesResult(PaginatedResult): +class ListResourcesResult(ListResult): """The server's response to a resources/list request from the client.""" resources: list[Resource] -class ListResourceTemplatesRequest( - Request[ListResourceTemplatesRequestParams | None, Literal["resources/templates/list"]] -): +class ListResourceTemplatesRequest(ListRequest[Literal["resources/templates/list"]]): """Sent from the client to request a list of resource templates the server has.""" method: Literal["resources/templates/list"] - params: ListResourceTemplatesRequestParams | None = None -class ListResourceTemplatesResult(PaginatedResult): +class ListResourceTemplatesResult(ListResult): """The server's response to a resources/templates/list request from the client.""" resourceTemplates: list[ResourceTemplate] @@ -629,7 +614,7 @@ class ResourceUpdatedNotification( params: ResourceUpdatedNotificationParams -class ListPromptsRequest(PaginatedRequest[Literal["prompts/list"]]): +class ListPromptsRequest(ListRequest[Literal["prompts/list"]]): """Sent from the client to request a list of prompts and prompt templates.""" method: Literal["prompts/list"] @@ -664,7 +649,7 @@ class Prompt(BaseMetadata): model_config = ConfigDict(extra="allow") -class ListPromptsResult(PaginatedResult): +class ListPromptsResult(ListResult): """The server's response to a prompts/list request from the client.""" prompts: list[Prompt] @@ -814,7 +799,7 @@ class PromptListChangedNotification( params: NotificationParams | None = None -class ListToolsRequest(PaginatedRequest[Literal["tools/list"]]): +class ListToolsRequest(ListRequest[Literal["tools/list"]]): """Sent from the client to request a list of tools the server has.""" method: Literal["tools/list"] @@ -892,7 +877,7 @@ class Tool(BaseMetadata): model_config = ConfigDict(extra="allow") -class ListToolsResult(PaginatedResult): +class ListToolsResult(ListResult): """The server's response to a tools/list request from the client.""" tools: list[Tool] From 6ed58df68909e644662da7e202fcc04e93a9b1ec Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Fri, 1 Aug 2025 17:15:25 -0700 Subject: [PATCH 06/15] fix: Update prompt manager to support prefix filtering and URI-based storage - Add prefix parameter to PromptManager.list_prompts() with path prefix behavior - Add _normalize_to_uri() method to convert names to prompt:// URIs - Update add_prompt() to use URIs as keys for consistent storage - Update get_prompt() to accept both names and URIs - Update FastMCP server to pass request object to lowlevel handlers - Fix test expectation for new path prefix behavior in list_templates This completes the implementation of consistent prefix-based filtering across all list operations (resources, templates, tools, and prompts). --- src/mcp/server/fastmcp/prompts/manager.py | 35 +++++++++++++------ src/mcp/server/fastmcp/server.py | 8 ++--- src/mcp/server/lowlevel/server.py | 2 +- .../resources/test_resource_manager.py | 7 ++-- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/mcp/server/fastmcp/prompts/manager.py b/src/mcp/server/fastmcp/prompts/manager.py index 6b01d91cd..65e9dec44 100644 --- a/src/mcp/server/fastmcp/prompts/manager.py +++ b/src/mcp/server/fastmcp/prompts/manager.py @@ -15,28 +15,43 @@ def __init__(self, warn_on_duplicate_prompts: bool = True): self._prompts: dict[str, Prompt] = {} self.warn_on_duplicate_prompts = warn_on_duplicate_prompts - def get_prompt(self, name: str) -> Prompt | None: - """Get prompt by name.""" - return self._prompts.get(name) + def _normalize_to_uri(self, name_or_uri: str) -> str: + """Convert name to URI if needed.""" + if name_or_uri.startswith("prompt://"): + return name_or_uri + return f"prompt://{name_or_uri}" - def list_prompts(self) -> list[Prompt]: - """List all registered prompts.""" - return list(self._prompts.values()) + def get_prompt(self, name: str) -> Prompt | None: + """Get prompt by name or URI.""" + uri = self._normalize_to_uri(name) + return self._prompts.get(uri) + + def list_prompts(self, prefix: str | None = None) -> list[Prompt]: + """List all registered prompts, optionally filtered by URI prefix.""" + prompts = list(self._prompts.values()) + if prefix: + # Ensure prefix ends with / for proper path matching + if not prefix.endswith("/"): + prefix = prefix + "/" + prompts = [p for p in prompts if str(p.uri).startswith(prefix)] + logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) + return prompts def add_prompt( self, prompt: Prompt, ) -> Prompt: """Add a prompt to the manager.""" - + logger.debug(f"Adding prompt: {prompt.name} with URI: {prompt.uri}") + # Check for duplicates - existing = self._prompts.get(prompt.name) + existing = self._prompts.get(prompt.uri) if existing: if self.warn_on_duplicate_prompts: - logger.warning(f"Prompt already exists: {prompt.name}") + logger.warning(f"Prompt already exists: {prompt.uri}") return existing - self._prompts[prompt.name] = prompt + self._prompts[prompt.uri] = prompt return prompt async def render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> list[Message]: diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index a2010e2cd..1d1625ef9 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -267,10 +267,10 @@ def _setup_handlers(self) -> None: self._mcp_server.get_prompt()(self.get_prompt) self._mcp_server.list_resource_templates()(self.list_resource_templates) - async def list_tools(self, request: types.ListToolsRequest) -> list[MCPTool]: + async def list_tools(self, request: types.ListToolsRequest | None = None) -> list[MCPTool]: """List all available tools, optionally filtered by prefix.""" prefix = None - if request.params: + if request and request.params: prefix = request.params.prefix tools = self._tool_manager.list_tools(prefix=prefix) return [ @@ -969,10 +969,10 @@ def streamable_http_app(self) -> Starlette: lifespan=lambda app: self.session_manager.run(), ) - async def list_prompts(self, request: types.ListPromptsRequest) -> list[MCPPrompt]: + async def list_prompts(self, request: types.ListPromptsRequest | None = None) -> list[MCPPrompt]: """List all available prompts, optionally filtered by prefix.""" prefix = None - if request.params: + if request and request.params: prefix = request.params.prefix prompts = self._prompt_manager.list_prompts(prefix=prefix) return [ diff --git a/src/mcp/server/lowlevel/server.py b/src/mcp/server/lowlevel/server.py index 0eadb5031..e6c6d9ca7 100644 --- a/src/mcp/server/lowlevel/server.py +++ b/src/mcp/server/lowlevel/server.py @@ -415,7 +415,7 @@ async def _get_cached_tool_definition(self, tool_name: str) -> types.Tool | None if tool_name not in self._tool_cache: if types.ListToolsRequest in self.request_handlers: logger.debug("Tool cache miss for %s, refreshing cache", tool_name) - await self.request_handlers[types.ListToolsRequest](None) + await self.request_handlers[types.ListToolsRequest](types.ListToolsRequest(method="tools/list")) tool = self._tool_cache.get(tool_name) if tool is None: diff --git a/tests/server/fastmcp/resources/test_resource_manager.py b/tests/server/fastmcp/resources/test_resource_manager.py index 689b1f6ae..c82ab465c 100644 --- a/tests/server/fastmcp/resources/test_resource_manager.py +++ b/tests/server/fastmcp/resources/test_resource_manager.py @@ -219,11 +219,10 @@ def product_func(product_id: str) -> str: assert len(user_123_templates) == 1 assert template2 in user_123_templates # users/{user_id}/posts/{post_id} matches - # Without trailing slash, both match + # Without trailing slash, it gets added automatically so only posts template matches user_123_no_slash = manager.list_templates(prefix="http://api.com/users/123") - assert len(user_123_no_slash) == 2 - assert template1 in user_123_no_slash - assert template2 in user_123_no_slash + assert len(user_123_no_slash) == 1 + assert template2 in user_123_no_slash # Only posts template has path after users/123/ # Test product prefix product_templates = manager.list_templates(prefix="http://api.com/products/") From 5d025a95788ddf03564d757582431fe4f8523819 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Fri, 1 Aug 2025 18:01:47 -0700 Subject: [PATCH 07/15] fix: Fix test failures after prefix filtering implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes all test failures that occurred after implementing consistent prefix-based filtering across tools, prompts, and resources. Changes: - Add required URI fields to all Tool instances in tests - Update all list_tools handlers to accept request parameter - Fix client session to use ListRequestParams for all list methods - Update test handlers in streamable_http, SSE, and WS tests The tests were failing because: 1. Tool objects now require a URI field 2. Low-level server list_tools handlers expect a request parameter 3. Client session was using old RequestParams class names All tests now pass except for one unrelated connection error. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/mcp/client/session.py | 4 ++-- src/mcp/server/fastmcp/prompts/manager.py | 2 +- tests/client/test_output_schema_validation.py | 14 +++++++++----- tests/client/test_session_group.py | 2 +- tests/issues/test_88_random_error.py | 4 +++- tests/server/test_cancel_handling.py | 3 ++- tests/server/test_lowlevel_input_validation.py | 6 +++++- tests/server/test_lowlevel_output_validation.py | 10 +++++++++- tests/server/test_lowlevel_tool_annotations.py | 3 ++- tests/shared/test_progress_notifications.py | 3 ++- tests/shared/test_session.py | 3 ++- tests/shared/test_sse.py | 7 +++++-- tests/shared/test_streamable_http.py | 12 ++++++++++-- tests/shared/test_ws.py | 3 ++- 14 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/mcp/client/session.py b/src/mcp/client/session.py index 91c7152ac..0f9c9fb59 100644 --- a/src/mcp/client/session.py +++ b/src/mcp/client/session.py @@ -225,7 +225,7 @@ async def list_resources(self, prefix: str | None = None, cursor: str | None = N """Send a resources/list request.""" params = None if cursor is not None or prefix is not None: - params = types.ListResourcesRequestParams(prefix=prefix, cursor=cursor) + params = types.ListRequestParams(prefix=prefix, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListResourcesRequest( @@ -244,7 +244,7 @@ async def list_resource_templates( """Send a resources/templates/list request.""" params = None if cursor is not None or prefix is not None: - params = types.ListResourceTemplatesRequestParams(prefix=prefix, cursor=cursor) + params = types.ListRequestParams(prefix=prefix, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListResourceTemplatesRequest( diff --git a/src/mcp/server/fastmcp/prompts/manager.py b/src/mcp/server/fastmcp/prompts/manager.py index 65e9dec44..e21c7f1bb 100644 --- a/src/mcp/server/fastmcp/prompts/manager.py +++ b/src/mcp/server/fastmcp/prompts/manager.py @@ -43,7 +43,7 @@ def add_prompt( ) -> Prompt: """Add a prompt to the manager.""" logger.debug(f"Adding prompt: {prompt.name} with URI: {prompt.uri}") - + # Check for duplicates existing = self._prompts.get(prompt.uri) if existing: diff --git a/tests/client/test_output_schema_validation.py b/tests/client/test_output_schema_validation.py index 242515b96..a6ddf6292 100644 --- a/tests/client/test_output_schema_validation.py +++ b/tests/client/test_output_schema_validation.py @@ -42,9 +42,10 @@ async def test_tool_structured_output_client_side_validation_basemodel(self): } @server.list_tools() - async def list_tools(): + async def list_tools(request): return [ Tool( + uri="tool://get_user", name="get_user", description="Get user data", inputSchema={"type": "object"}, @@ -81,9 +82,10 @@ async def test_tool_structured_output_client_side_validation_primitive(self): } @server.list_tools() - async def list_tools(): + async def list_tools(request): return [ Tool( + uri="tool://calculate", name="calculate", description="Calculate something", inputSchema={"type": "object"}, @@ -112,9 +114,10 @@ async def test_tool_structured_output_client_side_validation_dict_typed(self): output_schema = {"type": "object", "additionalProperties": {"type": "integer"}, "title": "get_scores_Output"} @server.list_tools() - async def list_tools(): + async def list_tools(request): return [ Tool( + uri="tool://get_scores", name="get_scores", description="Get scores", inputSchema={"type": "object"}, @@ -147,9 +150,10 @@ async def test_tool_structured_output_client_side_validation_missing_required(se } @server.list_tools() - async def list_tools(): + async def list_tools(request): return [ Tool( + uri="tool://get_person", name="get_person", description="Get person data", inputSchema={"type": "object"}, @@ -175,7 +179,7 @@ async def test_tool_not_listed_warning(self, caplog): server = Server("test-server") @server.list_tools() - async def list_tools(): + async def list_tools(request): # Return empty list - tool is not listed return [] diff --git a/tests/client/test_session_group.py b/tests/client/test_session_group.py index 16a887e00..3c193f740 100644 --- a/tests/client/test_session_group.py +++ b/tests/client/test_session_group.py @@ -58,7 +58,7 @@ def hook(name, server_info): return f"{(server_info.name)}-{name}" mcp_session_group = ClientSessionGroup(component_name_hook=hook) - mcp_session_group._tools = {"server1-my_tool": types.Tool(name="my_tool", inputSchema={})} + mcp_session_group._tools = {"server1-my_tool": types.Tool(uri="tool://my_tool", name="my_tool", inputSchema={})} mcp_session_group._tool_to_session = {"server1-my_tool": mock_session} text_content = types.TextContent(type="text", text="OK") mock_session.call_tool.return_value = types.CallToolResult(content=[text_content]) diff --git a/tests/issues/test_88_random_error.py b/tests/issues/test_88_random_error.py index c3570a39c..9adaed540 100644 --- a/tests/issues/test_88_random_error.py +++ b/tests/issues/test_88_random_error.py @@ -31,14 +31,16 @@ async def test_notification_validation_error(tmp_path: Path): slow_request_lock = anyio.Event() @server.list_tools() - async def list_tools() -> list[types.Tool]: + async def list_tools(request) -> list[types.Tool]: return [ types.Tool( + uri="tool://slow", name="slow", description="A slow tool", inputSchema={"type": "object"}, ), types.Tool( + uri="tool://fast", name="fast", description="A fast tool", inputSchema={"type": "object"}, diff --git a/tests/server/test_cancel_handling.py b/tests/server/test_cancel_handling.py index 44b9a924d..e649e7c01 100644 --- a/tests/server/test_cancel_handling.py +++ b/tests/server/test_cancel_handling.py @@ -31,9 +31,10 @@ async def test_server_remains_functional_after_cancel(): first_request_id = None @server.list_tools() - async def handle_list_tools() -> list[Tool]: + async def handle_list_tools(request) -> list[Tool]: return [ Tool( + uri="tool://test_tool", name="test_tool", description="Tool for testing", inputSchema={}, diff --git a/tests/server/test_lowlevel_input_validation.py b/tests/server/test_lowlevel_input_validation.py index 250159733..96bfd4cd8 100644 --- a/tests/server/test_lowlevel_input_validation.py +++ b/tests/server/test_lowlevel_input_validation.py @@ -35,7 +35,7 @@ async def run_tool_test( server = Server("test") @server.list_tools() - async def list_tools(): + async def list_tools(request): return tools @server.call_tool() @@ -99,6 +99,7 @@ async def handle_messages(): def create_add_tool() -> Tool: """Create a standard 'add' tool for testing.""" return Tool( + uri="tool://add", name="add", description="Add two numbers", inputSchema={ @@ -189,6 +190,7 @@ async def test_cache_refresh_on_missing_tool(): """Test that tool cache is refreshed when tool is not found.""" tools = [ Tool( + uri="tool://multiply", name="multiply", description="Multiply two numbers", inputSchema={ @@ -230,6 +232,7 @@ async def test_enum_constraint_validation(): """Test that enum constraints are validated.""" tools = [ Tool( + uri="tool://greet", name="greet", description="Greet someone", inputSchema={ @@ -267,6 +270,7 @@ async def test_tool_not_in_list_logs_warning(caplog): """Test that calling a tool not in list_tools logs a warning and skips validation.""" tools = [ Tool( + uri="tool://add", name="add", description="Add two numbers", inputSchema={ diff --git a/tests/server/test_lowlevel_output_validation.py b/tests/server/test_lowlevel_output_validation.py index 39f0d970d..ee5040993 100644 --- a/tests/server/test_lowlevel_output_validation.py +++ b/tests/server/test_lowlevel_output_validation.py @@ -35,7 +35,7 @@ async def run_tool_test( server = Server("test") @server.list_tools() - async def list_tools(): + async def list_tools(request): return tools @server.call_tool() @@ -101,6 +101,7 @@ async def test_content_only_without_output_schema(): """Test returning content only when no outputSchema is defined.""" tools = [ Tool( + uri="tool://echo", name="echo", description="Echo a message", inputSchema={ @@ -140,6 +141,7 @@ async def test_dict_only_without_output_schema(): """Test returning dict only when no outputSchema is defined.""" tools = [ Tool( + uri="tool://get_info", name="get_info", description="Get structured information", inputSchema={ @@ -177,6 +179,7 @@ async def test_both_content_and_dict_without_output_schema(): """Test returning both content and dict when no outputSchema is defined.""" tools = [ Tool( + uri="tool://process", name="process", description="Process data", inputSchema={ @@ -215,6 +218,7 @@ async def test_content_only_with_output_schema_error(): """Test error when outputSchema is defined but only content is returned.""" tools = [ Tool( + uri="tool://structured_tool", name="structured_tool", description="Tool expecting structured output", inputSchema={ @@ -254,6 +258,7 @@ async def test_valid_dict_with_output_schema(): """Test valid dict output matching outputSchema.""" tools = [ Tool( + uri="tool://calc", name="calc", description="Calculate result", inputSchema={ @@ -303,6 +308,7 @@ async def test_invalid_dict_with_output_schema(): """Test dict output that doesn't match outputSchema.""" tools = [ Tool( + uri="tool://user_info", name="user_info", description="Get user information", inputSchema={ @@ -347,6 +353,7 @@ async def test_both_content_and_valid_dict_with_output_schema(): """Test returning both content and valid dict with outputSchema.""" tools = [ Tool( + uri="tool://analyze", name="analyze", description="Analyze data", inputSchema={ @@ -394,6 +401,7 @@ async def test_output_schema_type_validation(): """Test outputSchema validates types correctly.""" tools = [ Tool( + uri="tool://stats", name="stats", description="Get statistics", inputSchema={ diff --git a/tests/server/test_lowlevel_tool_annotations.py b/tests/server/test_lowlevel_tool_annotations.py index 2eb3b7ddb..525ceaa1d 100644 --- a/tests/server/test_lowlevel_tool_annotations.py +++ b/tests/server/test_lowlevel_tool_annotations.py @@ -20,9 +20,10 @@ async def test_lowlevel_server_tool_annotations(): # Create a tool with annotations @server.list_tools() - async def list_tools(): + async def list_tools(request): return [ Tool( + uri="tool://echo", name="echo", description="Echo a message back", inputSchema={ diff --git a/tests/shared/test_progress_notifications.py b/tests/shared/test_progress_notifications.py index 93cc712b4..5a08e8004 100644 --- a/tests/shared/test_progress_notifications.py +++ b/tests/shared/test_progress_notifications.py @@ -76,9 +76,10 @@ async def handle_progress( # Register list tool handler @server.list_tools() - async def handle_list_tools() -> list[types.Tool]: + async def handle_list_tools(request) -> list[types.Tool]: return [ types.Tool( + uri="tool://test_tool", name="test_tool", description="A tool that sends progress notifications list: # Register the tool so it shows up in list_tools @server.list_tools() - async def handle_list_tools() -> list[types.Tool]: + async def handle_list_tools(request) -> list[types.Tool]: return [ types.Tool( + uri="tool://slow_tool", name="slow_tool", description="A slow tool that takes 10 seconds to complete", inputSchema={}, diff --git a/tests/shared/test_sse.py b/tests/shared/test_sse.py index 39ae13524..494c02165 100644 --- a/tests/shared/test_sse.py +++ b/tests/shared/test_sse.py @@ -64,9 +64,10 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: raise McpError(error=ErrorData(code=404, message="OOPS! no resource with that URI was found")) @self.list_tools() - async def handle_list_tools() -> list[Tool]: + async def handle_list_tools(request) -> list[Tool]: return [ Tool( + uri="tool://test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, @@ -323,14 +324,16 @@ async def handle_call_tool(name: str, args: dict) -> list[TextContent]: return [TextContent(type="text", text=f"Called {name}")] @self.list_tools() - async def handle_list_tools() -> list[Tool]: + async def handle_list_tools(request) -> list[Tool]: return [ Tool( + uri="tool://echo_headers", name="echo_headers", description="Echoes request headers", inputSchema={"type": "object", "properties": {}}, ), Tool( + uri="tool://echo_context", name="echo_context", description="Echoes request context", inputSchema={ diff --git a/tests/shared/test_streamable_http.py b/tests/shared/test_streamable_http.py index 3fea54f0b..05dfbabf5 100644 --- a/tests/shared/test_streamable_http.py +++ b/tests/shared/test_streamable_http.py @@ -138,34 +138,40 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: raise ValueError(f"Unknown resource: {uri}") @self.list_tools() - async def handle_list_tools() -> list[Tool]: + async def handle_list_tools(request) -> list[Tool]: return [ Tool( + uri="tool://test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, ), Tool( + uri="tool://test_tool_with_standalone_notification", name="test_tool_with_standalone_notification", description="A test tool that sends a notification", inputSchema={"type": "object", "properties": {}}, ), Tool( + uri="tool://long_running_with_checkpoints", name="long_running_with_checkpoints", description="A long-running tool that sends periodic notifications", inputSchema={"type": "object", "properties": {}}, ), Tool( + uri="tool://test_sampling_tool", name="test_sampling_tool", description="A tool that triggers server-side sampling", inputSchema={"type": "object", "properties": {}}, ), Tool( + uri="tool://wait_for_lock_with_notification", name="wait_for_lock_with_notification", description="A tool that sends a notification and waits for lock", inputSchema={"type": "object", "properties": {}}, ), Tool( + uri="tool://release_lock", name="release_lock", description="A tool that releases the lock", inputSchema={"type": "object", "properties": {}}, @@ -1277,14 +1283,16 @@ def __init__(self): super().__init__("ContextAwareServer") @self.list_tools() - async def handle_list_tools() -> list[Tool]: + async def handle_list_tools(request) -> list[Tool]: return [ Tool( + uri="tool://echo_headers", name="echo_headers", description="Echo request headers from context", inputSchema={"type": "object", "properties": {}}, ), Tool( + uri="tool://echo_context", name="echo_context", description="Echo request context with custom data", inputSchema={ diff --git a/tests/shared/test_ws.py b/tests/shared/test_ws.py index 5081f1d53..7e0d8d208 100644 --- a/tests/shared/test_ws.py +++ b/tests/shared/test_ws.py @@ -57,9 +57,10 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: raise McpError(error=ErrorData(code=404, message="OOPS! no resource with that URI was found")) @self.list_tools() - async def handle_list_tools() -> list[Tool]: + async def handle_list_tools(request) -> list[Tool]: return [ Tool( + uri="tool://test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, From a378a50920fb0152df863b9509b22fa4a43e3575 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sat, 2 Aug 2025 16:01:02 -0700 Subject: [PATCH 08/15] refactor: consolidate URI handling and implement DRY principles - Add TOOL_SCHEME and PROMPT_SCHEME constants in mcp/types.py - Create common URI utilities in uri_utils.py for normalization and prefix filtering - Update Tool and Prompt classes to auto-generate URIs when not provided - Replace hardcoded URI schemes throughout codebase with constants - Fix prefix filtering to handle partial matches correctly - Update example files to match expected function signatures --- README.md | 6 +- .../simple-prompt/mcp_simple_prompt/server.py | 2 +- .../server.py | 2 +- .../mcp_simple_streamablehttp/server.py | 2 +- .../simple-tool/mcp_simple_tool/server.py | 2 +- .../servers/structured_output_lowlevel.py | 2 +- examples/snippets/servers/lowlevel/basic.py | 2 +- .../snippets/servers/lowlevel/lifespan.py | 2 +- .../servers/lowlevel/structured_output.py | 2 +- src/mcp/client/session.py | 14 +- src/mcp/server/fastmcp/prompts/base.py | 4 +- src/mcp/server/fastmcp/prompts/manager.py | 11 +- .../server/fastmcp/prompts/prompt_manager.py | 15 +- .../fastmcp/resources/resource_manager.py | 7 +- src/mcp/server/fastmcp/tools/base.py | 4 +- src/mcp/server/fastmcp/tools/tool_manager.py | 17 +- src/mcp/server/fastmcp/uri_utils.py | 62 ++++++ src/mcp/types.py | 38 +++- tests/client/test_output_schema_validation.py | 10 +- tests/client/test_session_group.py | 5 +- tests/issues/test_88_random_error.py | 6 +- tests/server/fastmcp/prompts/test_manager.py | 142 ++++++++++++++ tests/server/fastmcp/test_server.py | 6 +- tests/server/fastmcp/test_title.py | 17 +- tests/server/fastmcp/test_tool_manager.py | 129 ++++++++++++- tests/server/fastmcp/test_uri_utils.py | 180 ++++++++++++++++++ tests/server/test_cancel_handling.py | 3 +- .../server/test_lowlevel_input_validation.py | 10 +- .../server/test_lowlevel_output_validation.py | 18 +- .../server/test_lowlevel_tool_annotations.py | 4 +- tests/server/test_session.py | 3 +- tests/shared/test_progress_notifications.py | 3 +- tests/shared/test_session.py | 3 +- tests/shared/test_sse.py | 7 +- tests/shared/test_streamable_http.py | 17 +- tests/shared/test_ws.py | 3 +- tests/test_types.py | 19 +- 37 files changed, 659 insertions(+), 120 deletions(-) create mode 100644 src/mcp/server/fastmcp/uri_utils.py create mode 100644 tests/server/fastmcp/test_uri_utils.py diff --git a/README.md b/README.md index 993b6006b..02fbae947 100644 --- a/README.md +++ b/README.md @@ -1125,7 +1125,7 @@ server = Server("example-server", lifespan=server_lifespan) @server.list_tools() -async def handle_list_tools() -> list[types.Tool]: +async def handle_list_tools(request: types.ListToolsRequest) -> list[types.Tool]: """List available tools.""" return [ types.Tool( @@ -1207,7 +1207,7 @@ server = Server("example-server") @server.list_prompts() -async def handle_list_prompts() -> list[types.Prompt]: +async def handle_list_prompts(request: types.ListPromptsRequest) -> list[types.Prompt]: """List available prompts.""" return [ types.Prompt( @@ -1286,7 +1286,7 @@ server = Server("example-server") @server.list_tools() -async def list_tools() -> list[types.Tool]: +async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: """List available tools with structured output schemas.""" return [ types.Tool( diff --git a/examples/servers/simple-prompt/mcp_simple_prompt/server.py b/examples/servers/simple-prompt/mcp_simple_prompt/server.py index b562cc932..4ffcf09a9 100644 --- a/examples/servers/simple-prompt/mcp_simple_prompt/server.py +++ b/examples/servers/simple-prompt/mcp_simple_prompt/server.py @@ -49,7 +49,7 @@ def main(port: int, transport: str) -> int: app = Server("mcp-simple-prompt") @app.list_prompts() - async def list_prompts() -> list[types.Prompt]: + async def list_prompts(request: types.ListPromptsRequest) -> list[types.Prompt]: return [ types.Prompt( name="simple", diff --git a/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py b/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py index 68f3ac6a6..330f683b1 100644 --- a/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py +++ b/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py @@ -69,7 +69,7 @@ async def call_tool(name: str, arguments: dict) -> list[types.ContentBlock]: ] @app.list_tools() - async def list_tools() -> list[types.Tool]: + async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: return [ types.Tool( name="start-notification-stream", diff --git a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py index 9c25cc569..1d9ee02f8 100644 --- a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py +++ b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py @@ -87,7 +87,7 @@ async def call_tool(name: str, arguments: dict) -> list[types.ContentBlock]: ] @app.list_tools() - async def list_tools() -> list[types.Tool]: + async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: return [ types.Tool( name="start-notification-stream", diff --git a/examples/servers/simple-tool/mcp_simple_tool/server.py b/examples/servers/simple-tool/mcp_simple_tool/server.py index bf3683c9e..9846a20cf 100644 --- a/examples/servers/simple-tool/mcp_simple_tool/server.py +++ b/examples/servers/simple-tool/mcp_simple_tool/server.py @@ -37,7 +37,7 @@ async def fetch_tool(name: str, arguments: dict) -> list[types.ContentBlock]: return await fetch_website(arguments["url"]) @app.list_tools() - async def list_tools() -> list[types.Tool]: + async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: return [ types.Tool( name="fetch", diff --git a/examples/servers/structured_output_lowlevel.py b/examples/servers/structured_output_lowlevel.py index 7f102ff8b..a678f7595 100644 --- a/examples/servers/structured_output_lowlevel.py +++ b/examples/servers/structured_output_lowlevel.py @@ -21,7 +21,7 @@ @server.list_tools() -async def list_tools() -> list[types.Tool]: +async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: """List available tools with their schemas.""" return [ types.Tool( diff --git a/examples/snippets/servers/lowlevel/basic.py b/examples/snippets/servers/lowlevel/basic.py index a5c4149df..6d494a134 100644 --- a/examples/snippets/servers/lowlevel/basic.py +++ b/examples/snippets/servers/lowlevel/basic.py @@ -15,7 +15,7 @@ @server.list_prompts() -async def handle_list_prompts() -> list[types.Prompt]: +async def handle_list_prompts(request: types.ListPromptsRequest) -> list[types.Prompt]: """List available prompts.""" return [ types.Prompt( diff --git a/examples/snippets/servers/lowlevel/lifespan.py b/examples/snippets/servers/lowlevel/lifespan.py index 61a9fe78e..947ce09fa 100644 --- a/examples/snippets/servers/lowlevel/lifespan.py +++ b/examples/snippets/servers/lowlevel/lifespan.py @@ -49,7 +49,7 @@ async def server_lifespan(_server: Server) -> AsyncIterator[dict]: @server.list_tools() -async def handle_list_tools() -> list[types.Tool]: +async def handle_list_tools(request: types.ListToolsRequest) -> list[types.Tool]: """List available tools.""" return [ types.Tool( diff --git a/examples/snippets/servers/lowlevel/structured_output.py b/examples/snippets/servers/lowlevel/structured_output.py index 0237c9ab3..af725e2a9 100644 --- a/examples/snippets/servers/lowlevel/structured_output.py +++ b/examples/snippets/servers/lowlevel/structured_output.py @@ -15,7 +15,7 @@ @server.list_tools() -async def list_tools() -> list[types.Tool]: +async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: """List available tools with structured output schemas.""" return [ types.Tool( diff --git a/src/mcp/client/session.py b/src/mcp/client/session.py index 0f9c9fb59..686d10f49 100644 --- a/src/mcp/client/session.py +++ b/src/mcp/client/session.py @@ -342,13 +342,16 @@ async def _validate_tool_result(self, name: str, result: types.CallToolResult) - except SchemaError as e: raise RuntimeError(f"Invalid schema for tool {name}: {e}") - async def list_prompts(self, cursor: str | None = None) -> types.ListPromptsResult: + async def list_prompts(self, prefix: str | None = None, cursor: str | None = None) -> types.ListPromptsResult: """Send a prompts/list request.""" + params = None + if cursor is not None or prefix is not None: + params = types.ListRequestParams(prefix=prefix, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListPromptsRequest( method="prompts/list", - params=types.ListRequestParams(cursor=cursor) if cursor is not None else None, + params=params, ) ), types.ListPromptsResult, @@ -391,13 +394,16 @@ async def complete( types.CompleteResult, ) - async def list_tools(self, cursor: str | None = None) -> types.ListToolsResult: + async def list_tools(self, prefix: str | None = None, cursor: str | None = None) -> types.ListToolsResult: """Send a tools/list request.""" + params = None + if cursor is not None or prefix is not None: + params = types.ListRequestParams(prefix=prefix, cursor=cursor) result = await self.send_request( types.ClientRequest( types.ListToolsRequest( method="tools/list", - params=types.ListRequestParams(cursor=cursor) if cursor is not None else None, + params=params, ) ), types.ListToolsResult, diff --git a/src/mcp/server/fastmcp/prompts/base.py b/src/mcp/server/fastmcp/prompts/base.py index 5117827de..2c8d296ec 100644 --- a/src/mcp/server/fastmcp/prompts/base.py +++ b/src/mcp/server/fastmcp/prompts/base.py @@ -7,7 +7,7 @@ import pydantic_core from pydantic import BaseModel, Field, TypeAdapter, validate_call -from mcp.types import ContentBlock, TextContent +from mcp.types import PROMPT_SCHEME, ContentBlock, TextContent class Message(BaseModel): @@ -67,7 +67,7 @@ class Prompt(BaseModel): def __init__(self, **data: Any) -> None: """Initialize Prompt, generating URI from name if not provided.""" if "uri" not in data and "name" in data: - data["uri"] = f"prompt://{data['name']}" + data["uri"] = f"{PROMPT_SCHEME}/{data['name']}" super().__init__(**data) @classmethod diff --git a/src/mcp/server/fastmcp/prompts/manager.py b/src/mcp/server/fastmcp/prompts/manager.py index e21c7f1bb..4b0e58d43 100644 --- a/src/mcp/server/fastmcp/prompts/manager.py +++ b/src/mcp/server/fastmcp/prompts/manager.py @@ -3,6 +3,7 @@ from typing import Any from mcp.server.fastmcp.prompts.base import Message, Prompt +from mcp.server.fastmcp.uri_utils import filter_by_prefix, normalize_to_prompt_uri from mcp.server.fastmcp.utilities.logging import get_logger logger = get_logger(__name__) @@ -17,9 +18,7 @@ def __init__(self, warn_on_duplicate_prompts: bool = True): def _normalize_to_uri(self, name_or_uri: str) -> str: """Convert name to URI if needed.""" - if name_or_uri.startswith("prompt://"): - return name_or_uri - return f"prompt://{name_or_uri}" + return normalize_to_prompt_uri(name_or_uri) def get_prompt(self, name: str) -> Prompt | None: """Get prompt by name or URI.""" @@ -29,11 +28,7 @@ def get_prompt(self, name: str) -> Prompt | None: def list_prompts(self, prefix: str | None = None) -> list[Prompt]: """List all registered prompts, optionally filtered by URI prefix.""" prompts = list(self._prompts.values()) - if prefix: - # Ensure prefix ends with / for proper path matching - if not prefix.endswith("/"): - prefix = prefix + "/" - prompts = [p for p in prompts if str(p.uri).startswith(prefix)] + prompts = filter_by_prefix(prompts, prefix, lambda p: str(p.uri)) logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) return prompts diff --git a/src/mcp/server/fastmcp/prompts/prompt_manager.py b/src/mcp/server/fastmcp/prompts/prompt_manager.py index c8e221205..3e8e9479d 100644 --- a/src/mcp/server/fastmcp/prompts/prompt_manager.py +++ b/src/mcp/server/fastmcp/prompts/prompt_manager.py @@ -1,6 +1,7 @@ """Prompt management functionality.""" from mcp.server.fastmcp.prompts.base import Prompt +from mcp.server.fastmcp.uri_utils import filter_by_prefix, normalize_to_prompt_uri from mcp.server.fastmcp.utilities.logging import get_logger logger = get_logger(__name__) @@ -15,19 +16,17 @@ def __init__(self, warn_on_duplicate_prompts: bool = True): def _normalize_to_uri(self, name_or_uri: str) -> str: """Convert name to URI if needed.""" - if name_or_uri.startswith("prompt://"): - return name_or_uri - return f"prompt://{name_or_uri}" + return normalize_to_prompt_uri(name_or_uri) def add_prompt(self, prompt: Prompt) -> Prompt: """Add a prompt to the manager.""" logger.debug(f"Adding prompt: {prompt.name} with URI: {prompt.uri}") - existing = self._prompts.get(prompt.uri) + existing = self._prompts.get(str(prompt.uri)) if existing: if self.warn_on_duplicate_prompts: logger.warning(f"Prompt already exists: {prompt.uri}") return existing - self._prompts[prompt.uri] = prompt + self._prompts[str(prompt.uri)] = prompt return prompt def get_prompt(self, name: str) -> Prompt | None: @@ -38,10 +37,6 @@ def get_prompt(self, name: str) -> Prompt | None: def list_prompts(self, prefix: str | None = None) -> list[Prompt]: """List all registered prompts, optionally filtered by URI prefix.""" prompts = list(self._prompts.values()) - if prefix: - # Ensure prefix ends with / for proper path matching - if not prefix.endswith("/"): - prefix = prefix + "/" - prompts = [p for p in prompts if str(p.uri).startswith(prefix)] + prompts = filter_by_prefix(prompts, prefix, lambda p: str(p.uri)) logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) return prompts diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index ed11c0536..544e41766 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -7,6 +7,7 @@ from mcp.server.fastmcp.resources.base import Resource from mcp.server.fastmcp.resources.templates import ResourceTemplate +from mcp.server.fastmcp.uri_utils import filter_by_prefix from mcp.server.fastmcp.utilities.logging import get_logger logger = get_logger(__name__) @@ -89,11 +90,7 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: def list_resources(self, prefix: str | None = None) -> list[Resource]: """List all registered resources, optionally filtered by URI prefix.""" resources = list(self._resources.values()) - if prefix: - # Ensure prefix ends with / for proper path matching - if not prefix.endswith("/"): - prefix = prefix + "/" - resources = [r for r in resources if str(r.uri).startswith(prefix)] + resources = filter_by_prefix(resources, prefix, lambda r: str(r.uri)) logger.debug("Listing resources", extra={"count": len(resources), "prefix": prefix}) return resources diff --git a/src/mcp/server/fastmcp/tools/base.py b/src/mcp/server/fastmcp/tools/base.py index 995045770..1751c367d 100644 --- a/src/mcp/server/fastmcp/tools/base.py +++ b/src/mcp/server/fastmcp/tools/base.py @@ -10,7 +10,7 @@ from mcp.server.fastmcp.exceptions import ToolError from mcp.server.fastmcp.utilities.func_metadata import FuncMetadata, func_metadata -from mcp.types import ToolAnnotations +from mcp.types import TOOL_SCHEME, ToolAnnotations if TYPE_CHECKING: from mcp.server.fastmcp.server import Context @@ -37,7 +37,7 @@ class Tool(BaseModel): def __init__(self, **data: Any) -> None: """Initialize Tool, generating URI from name if not provided.""" if "uri" not in data and "name" in data: - data["uri"] = f"tool://{data['name']}" + data["uri"] = f"{TOOL_SCHEME}/{data['name']}" super().__init__(**data) @cached_property diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index bc8ec4948..db21bf964 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -5,6 +5,7 @@ from mcp.server.fastmcp.exceptions import ToolError from mcp.server.fastmcp.tools.base import Tool +from mcp.server.fastmcp.uri_utils import filter_by_prefix, normalize_to_tool_uri from mcp.server.fastmcp.utilities.logging import get_logger from mcp.shared.context import LifespanContextT, RequestT from mcp.types import ToolAnnotations @@ -30,15 +31,13 @@ def __init__( for tool in tools: if warn_on_duplicate_tools and tool.uri in self._tools: logger.warning(f"Tool already exists: {tool.uri}") - self._tools[tool.uri] = tool + self._tools[str(tool.uri)] = tool self.warn_on_duplicate_tools = warn_on_duplicate_tools def _normalize_to_uri(self, name_or_uri: str) -> str: """Convert name to URI if needed.""" - if name_or_uri.startswith("tool://"): - return name_or_uri - return f"tool://{name_or_uri}" + return normalize_to_tool_uri(name_or_uri) def get_tool(self, name: str) -> Tool | None: """Get tool by name or URI.""" @@ -48,11 +47,7 @@ def get_tool(self, name: str) -> Tool | None: def list_tools(self, prefix: str | None = None) -> list[Tool]: """List all registered tools, optionally filtered by URI prefix.""" tools = list(self._tools.values()) - if prefix: - # Ensure prefix ends with / for proper path matching - if not prefix.endswith("/"): - prefix = prefix + "/" - tools = [t for t in tools if str(t.uri).startswith(prefix)] + tools = filter_by_prefix(tools, prefix, lambda t: str(t.uri)) logger.debug("Listing tools", extra={"count": len(tools), "prefix": prefix}) return tools @@ -74,12 +69,12 @@ def add_tool( annotations=annotations, structured_output=structured_output, ) - existing = self._tools.get(tool.uri) + existing = self._tools.get(str(tool.uri)) if existing: if self.warn_on_duplicate_tools: logger.warning(f"Tool already exists: {tool.uri}") return existing - self._tools[tool.uri] = tool + self._tools[str(tool.uri)] = tool return tool async def call_tool( diff --git a/src/mcp/server/fastmcp/uri_utils.py b/src/mcp/server/fastmcp/uri_utils.py new file mode 100644 index 000000000..01dfe846b --- /dev/null +++ b/src/mcp/server/fastmcp/uri_utils.py @@ -0,0 +1,62 @@ +"""Common URI utilities for FastMCP.""" + +from collections.abc import Callable +from typing import TypeVar + +from mcp.types import PROMPT_SCHEME, TOOL_SCHEME + +T = TypeVar("T") + + +def normalize_to_uri(name_or_uri: str, scheme: str) -> str: + """Convert name to URI if needed. + + Args: + name_or_uri: Either a name or a full URI + scheme: The URI scheme to use (e.g., TOOL_SCHEME or PROMPT_SCHEME) + + Returns: + A properly formatted URI + """ + if name_or_uri.startswith(scheme): + return name_or_uri + return f"{scheme}/{name_or_uri}" + + +def normalize_to_tool_uri(name_or_uri: str) -> str: + """Convert name to tool URI if needed.""" + return normalize_to_uri(name_or_uri, TOOL_SCHEME) + + +def normalize_to_prompt_uri(name_or_uri: str) -> str: + """Convert name to prompt URI if needed.""" + return normalize_to_uri(name_or_uri, PROMPT_SCHEME) + + +def filter_by_prefix(items: list[T], prefix: str | None, uri_getter: Callable[[T], str]) -> list[T]: + """Filter items by URI prefix. + + Args: + items: List of items to filter + prefix: Optional prefix to filter by. If None, returns all items. + uri_getter: Function to extract URI from an item + + Returns: + Filtered list of items + """ + if not prefix: + return items + + # Filter items where the URI starts with the prefix + filtered: list[T] = [] + for item in items: + uri = uri_getter(item) + if uri.startswith(prefix): + # If prefix ends with a separator, we already have a proper boundary + if prefix.endswith(("/", "?", "#")): + filtered.append(item) + # Otherwise check if it's an exact match or if the next character is a separator + elif len(uri) == len(prefix) or uri[len(prefix)] in ("/", "?", "#"): + filtered.append(item) + + return filtered diff --git a/src/mcp/types.py b/src/mcp/types.py index 9c65fc31d..7bee55de4 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -1,10 +1,14 @@ from collections.abc import Callable from typing import Annotated, Any, Generic, Literal, TypeAlias, TypeVar -from pydantic import BaseModel, ConfigDict, Field, FileUrl, RootModel, model_validator -from pydantic.networks import AnyUrl, UrlConstraints +from pydantic import AnyUrl, BaseModel, ConfigDict, Field, FileUrl, RootModel, model_validator +from pydantic.networks import UrlConstraints from typing_extensions import deprecated +# URI scheme constants +TOOL_SCHEME = "tool:/" +PROMPT_SCHEME = "prompt:/" + """ Model Context Protocol bindings for Python @@ -437,8 +441,10 @@ class Resource(BaseMetadata): def validate_uri_scheme(self) -> "Resource": """Ensure resource URI doesn't use reserved schemes.""" uri_str = str(self.uri) - if uri_str.startswith(("tool://", "prompt://")): - raise ValueError(f"Resource URI cannot use reserved schemes 'tool://' or 'prompt://', got: {self.uri}") + if uri_str.startswith((TOOL_SCHEME, PROMPT_SCHEME)): + raise ValueError( + f"Resource URI cannot use reserved schemes '{TOOL_SCHEME}' or '{PROMPT_SCHEME}', got: {self.uri}" + ) return self @@ -635,8 +641,10 @@ class PromptArgument(BaseModel): class Prompt(BaseMetadata): """A prompt or prompt template that the server offers.""" - uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=["prompt"], host_required=False)] - """URI for the prompt. Must use 'prompt' scheme.""" + uri: ( + Annotated[AnyUrl, UrlConstraints(allowed_schemes=[PROMPT_SCHEME.rstrip(":/ ")], host_required=False)] | None + ) = None + """URI for the prompt. Auto-generated if not provided.""" description: str | None = None """An optional description of what this prompt provides.""" arguments: list[PromptArgument] | None = None @@ -648,6 +656,12 @@ class Prompt(BaseMetadata): """ model_config = ConfigDict(extra="allow") + def __init__(self, **data: Any) -> None: + """Initialize prompt with auto-generated URI if not provided.""" + if "uri" not in data: + data["uri"] = AnyUrl(f"{PROMPT_SCHEME}/{data['name']}") + super().__init__(**data) + class ListPromptsResult(ListResult): """The server's response to a prompts/list request from the client.""" @@ -856,8 +870,10 @@ class ToolAnnotations(BaseModel): class Tool(BaseMetadata): """Definition for a tool the client can call.""" - uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=["tool"], host_required=False)] - """URI for the tool. Must use 'tool' scheme.""" + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[TOOL_SCHEME.rstrip(":/ ")], host_required=False)] | None = ( + None + ) + """URI for the tool. Auto-generated if not provided.""" description: str | None = None """A human-readable description of the tool.""" inputSchema: dict[str, Any] @@ -876,6 +892,12 @@ class Tool(BaseMetadata): """ model_config = ConfigDict(extra="allow") + def __init__(self, **data: Any) -> None: + """Initialize tool with auto-generated URI if not provided.""" + if "uri" not in data: + data["uri"] = AnyUrl(f"{TOOL_SCHEME}/{data['name']}") + super().__init__(**data) + class ListToolsResult(ListResult): """The server's response to a tools/list request from the client.""" diff --git a/tests/client/test_output_schema_validation.py b/tests/client/test_output_schema_validation.py index a6ddf6292..c3b1b256c 100644 --- a/tests/client/test_output_schema_validation.py +++ b/tests/client/test_output_schema_validation.py @@ -8,7 +8,7 @@ from mcp.shared.memory import ( create_connected_server_and_client_session as client_session, ) -from mcp.types import Tool +from mcp.types import TOOL_SCHEME, Tool @contextmanager @@ -45,7 +45,7 @@ async def test_tool_structured_output_client_side_validation_basemodel(self): async def list_tools(request): return [ Tool( - uri="tool://get_user", + uri=f"{TOOL_SCHEME}/get_user", name="get_user", description="Get user data", inputSchema={"type": "object"}, @@ -85,7 +85,7 @@ async def test_tool_structured_output_client_side_validation_primitive(self): async def list_tools(request): return [ Tool( - uri="tool://calculate", + uri=f"{TOOL_SCHEME}/calculate", name="calculate", description="Calculate something", inputSchema={"type": "object"}, @@ -117,7 +117,7 @@ async def test_tool_structured_output_client_side_validation_dict_typed(self): async def list_tools(request): return [ Tool( - uri="tool://get_scores", + uri=f"{TOOL_SCHEME}/get_scores", name="get_scores", description="Get scores", inputSchema={"type": "object"}, @@ -153,7 +153,7 @@ async def test_tool_structured_output_client_side_validation_missing_required(se async def list_tools(request): return [ Tool( - uri="tool://get_person", + uri=f"{TOOL_SCHEME}/get_person", name="get_person", description="Get person data", inputSchema={"type": "object"}, diff --git a/tests/client/test_session_group.py b/tests/client/test_session_group.py index 3c193f740..f5a3ced24 100644 --- a/tests/client/test_session_group.py +++ b/tests/client/test_session_group.py @@ -12,6 +12,7 @@ ) from mcp.client.stdio import StdioServerParameters from mcp.shared.exceptions import McpError +from mcp.types import TOOL_SCHEME @pytest.fixture @@ -58,7 +59,9 @@ def hook(name, server_info): return f"{(server_info.name)}-{name}" mcp_session_group = ClientSessionGroup(component_name_hook=hook) - mcp_session_group._tools = {"server1-my_tool": types.Tool(uri="tool://my_tool", name="my_tool", inputSchema={})} + mcp_session_group._tools = { + "server1-my_tool": types.Tool(uri=f"{TOOL_SCHEME}/my_tool", name="my_tool", inputSchema={}) + } mcp_session_group._tool_to_session = {"server1-my_tool": mock_session} text_content = types.TextContent(type="text", text="OK") mock_session.call_tool.return_value = types.CallToolResult(content=[text_content]) diff --git a/tests/issues/test_88_random_error.py b/tests/issues/test_88_random_error.py index 9adaed540..30e23d555 100644 --- a/tests/issues/test_88_random_error.py +++ b/tests/issues/test_88_random_error.py @@ -12,7 +12,7 @@ from mcp.client.session import ClientSession from mcp.server.lowlevel import Server from mcp.shared.exceptions import McpError -from mcp.types import ContentBlock, TextContent +from mcp.types import TOOL_SCHEME, ContentBlock, TextContent @pytest.mark.anyio @@ -34,13 +34,13 @@ async def test_notification_validation_error(tmp_path: Path): async def list_tools(request) -> list[types.Tool]: return [ types.Tool( - uri="tool://slow", + uri=f"{TOOL_SCHEME}/slow", name="slow", description="A slow tool", inputSchema={"type": "object"}, ), types.Tool( - uri="tool://fast", + uri=f"{TOOL_SCHEME}/fast", name="fast", description="A fast tool", inputSchema={"type": "object"}, diff --git a/tests/server/fastmcp/prompts/test_manager.py b/tests/server/fastmcp/prompts/test_manager.py index 82b234638..90bb317b1 100644 --- a/tests/server/fastmcp/prompts/test_manager.py +++ b/tests/server/fastmcp/prompts/test_manager.py @@ -2,6 +2,7 @@ from mcp.server.fastmcp.prompts.base import Prompt, TextContent, UserMessage from mcp.server.fastmcp.prompts.manager import PromptManager +from mcp.types import PROMPT_SCHEME class TestPromptManager: @@ -61,6 +62,80 @@ def fn2() -> str: assert len(prompts) == 2 assert prompts == [prompt1, prompt2] + def test_list_prompts_with_prefix(self): + """Test listing prompts with prefix filtering.""" + + def greeting_hello() -> str: + return "Hello!" + + def greeting_goodbye() -> str: + return "Goodbye!" + + def question_name() -> str: + return "What's your name?" + + def question_age() -> str: + return "How old are you?" + + manager = PromptManager() + + # Create prompts with custom URIs + hello_prompt = Prompt.from_function(greeting_hello) + hello_prompt.uri = f"{PROMPT_SCHEME}/greeting/hello" + + goodbye_prompt = Prompt.from_function(greeting_goodbye) + goodbye_prompt.uri = f"{PROMPT_SCHEME}/greeting/goodbye" + + name_prompt = Prompt.from_function(question_name) + name_prompt.uri = f"{PROMPT_SCHEME}/question/name" + + age_prompt = Prompt.from_function(question_age) + age_prompt.uri = f"{PROMPT_SCHEME}/question/age" + + # Add prompts directly to manager's internal storage + manager._prompts = { + str(hello_prompt.uri): hello_prompt, + str(goodbye_prompt.uri): goodbye_prompt, + str(name_prompt.uri): name_prompt, + str(age_prompt.uri): age_prompt, + } + + # Test listing all prompts + all_prompts = manager.list_prompts() + assert len(all_prompts) == 4 + + # Test prefix filtering - greeting prompts + greeting_prompts = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/") + assert len(greeting_prompts) == 2 + assert all(str(p.uri).startswith(f"{PROMPT_SCHEME}/greeting/") for p in greeting_prompts) + assert hello_prompt in greeting_prompts + assert goodbye_prompt in greeting_prompts + + # Test prefix filtering - question prompts + question_prompts = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/question/") + assert len(question_prompts) == 2 + assert all(str(p.uri).startswith(f"{PROMPT_SCHEME}/question/") for p in question_prompts) + assert name_prompt in question_prompts + assert age_prompt in question_prompts + + # Test exact URI match + hello_prompts = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/hello") + assert len(hello_prompts) == 1 + assert hello_prompts[0] == hello_prompt + + # Test partial prefix doesn't match + no_partial = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/h") + assert len(no_partial) == 0 # Won't match because next char is 'e' not a separator + + # Test no matches + no_matches = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/nonexistent") + assert len(no_matches) == 0 + + # Test with trailing slash + greeting_prompts_slash = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/") + assert len(greeting_prompts_slash) == 2 + assert greeting_prompts_slash == greeting_prompts + @pytest.mark.anyio async def test_render_prompt(self): """Test rendering a prompt.""" @@ -106,3 +181,70 @@ def fn(name: str) -> str: manager.add_prompt(prompt) with pytest.raises(ValueError, match="Missing required arguments"): await manager.render_prompt("fn") + + def test_get_prompt_by_uri(self): + """Test getting prompts by their URI.""" + + def greeting() -> str: + return "Hello!" + + def custom_prompt() -> str: + return "Custom message" + + manager = PromptManager() + + # Add prompt with default URI + manager.add_prompt(Prompt.from_function(greeting)) + + # Add prompt with custom URI + custom = Prompt.from_function(custom_prompt) + custom.uri = f"{PROMPT_SCHEME}/custom/messages/welcome" + manager._prompts[str(custom.uri)] = custom + + # Get by name + prompt = manager.get_prompt("greeting") + assert prompt is not None + assert prompt.name == "greeting" + + # Get by default URI + prompt_by_uri = manager.get_prompt(f"{PROMPT_SCHEME}/greeting") + assert prompt_by_uri is not None + assert prompt_by_uri.name == "greeting" + assert prompt_by_uri == prompt + + # Get by custom URI + custom_by_uri = manager.get_prompt(f"{PROMPT_SCHEME}/custom/messages/welcome") + assert custom_by_uri is not None + assert custom_by_uri == custom + + @pytest.mark.anyio + async def test_render_prompt_by_uri(self): + """Test rendering prompts by their URI.""" + + def welcome(name: str) -> str: + return f"Welcome, {name}!" + + def farewell(name: str) -> str: + return f"Goodbye, {name}!" + + manager = PromptManager() + + # Add prompt with default URI + manager.add_prompt(Prompt.from_function(welcome)) + + # Add prompt with custom URI + farewell_prompt = Prompt.from_function(farewell) + farewell_prompt.uri = f"{PROMPT_SCHEME}/custom/farewell" + manager._prompts[str(farewell_prompt.uri)] = farewell_prompt + + # Render by default URI + messages = await manager.render_prompt(f"{PROMPT_SCHEME}/welcome", arguments={"name": "Alice"}) + assert messages == [UserMessage(content=TextContent(type="text", text="Welcome, Alice!"))] + + # Render by custom URI + messages = await manager.render_prompt(f"{PROMPT_SCHEME}/custom/farewell", arguments={"name": "Bob"}) + assert messages == [UserMessage(content=TextContent(type="text", text="Goodbye, Bob!"))] + + # Should still work with name + messages = await manager.render_prompt("welcome", arguments={"name": "Charlie"}) + assert messages == [UserMessage(content=TextContent(type="text", text="Welcome, Charlie!"))] diff --git a/tests/server/fastmcp/test_server.py b/tests/server/fastmcp/test_server.py index d9afc6d98..f69bc720b 100644 --- a/tests/server/fastmcp/test_server.py +++ b/tests/server/fastmcp/test_server.py @@ -16,6 +16,8 @@ create_connected_server_and_client_session as client_session, ) from mcp.types import ( + PROMPT_SCHEME, + TOOL_SCHEME, AudioContent, BlobResourceContents, ContentBlock, @@ -219,7 +221,7 @@ async def test_list_tools(self): assert len(tools.tools) == 1 # Verify URI is generated tool = tools.tools[0] - assert str(tool.uri) == "tool://tool_fn" + assert str(tool.uri) == f"{TOOL_SCHEME}/tool_fn" @pytest.mark.anyio async def test_call_tool(self): @@ -961,7 +963,7 @@ def fn(name: str, optional: str = "default") -> str: prompt = result.prompts[0] assert prompt.name == "fn" # Verify URI is generated - assert str(prompt.uri) == "prompt://fn" + assert str(prompt.uri) == f"{PROMPT_SCHEME}/fn" assert prompt.arguments is not None assert len(prompt.arguments) == 2 assert prompt.arguments[0].name == "name" diff --git a/tests/server/fastmcp/test_title.py b/tests/server/fastmcp/test_title.py index 976565c05..e6f3f9f5d 100644 --- a/tests/server/fastmcp/test_title.py +++ b/tests/server/fastmcp/test_title.py @@ -7,7 +7,7 @@ from mcp.server.fastmcp.resources import FunctionResource from mcp.shared.memory import create_connected_server_and_client_session from mcp.shared.metadata_utils import get_display_name -from mcp.types import Prompt, Resource, ResourceTemplate, Tool, ToolAnnotations +from mcp.types import PROMPT_SCHEME, TOOL_SCHEME, Prompt, Resource, ResourceTemplate, Tool, ToolAnnotations @pytest.mark.anyio @@ -181,20 +181,23 @@ async def test_get_display_name_utility(): """Test the get_display_name utility function.""" # Test tool precedence: title > annotations.title > name - tool_name_only = Tool(name="test_tool", uri="tool://test_tool", inputSchema={}) + tool_name_only = Tool(name="test_tool", uri=f"{TOOL_SCHEME}/test_tool", inputSchema={}) assert get_display_name(tool_name_only) == "test_tool" - tool_with_title = Tool(name="test_tool", uri="tool://test_tool", title="Test Tool", inputSchema={}) + tool_with_title = Tool(name="test_tool", uri=f"{TOOL_SCHEME}/test_tool", title="Test Tool", inputSchema={}) assert get_display_name(tool_with_title) == "Test Tool" tool_with_annotations = Tool( - name="test_tool", uri="tool://test_tool", inputSchema={}, annotations=ToolAnnotations(title="Annotated Tool") + name="test_tool", + uri=f"{TOOL_SCHEME}/test_tool", + inputSchema={}, + annotations=ToolAnnotations(title="Annotated Tool"), ) assert get_display_name(tool_with_annotations) == "Annotated Tool" tool_with_both = Tool( name="test_tool", - uri="tool://test_tool", + uri=f"{TOOL_SCHEME}/test_tool", title="Primary Title", inputSchema={}, annotations=ToolAnnotations(title="Secondary Title"), @@ -208,10 +211,10 @@ async def test_get_display_name_utility(): resource_with_title = Resource(uri=AnyUrl("file://test"), name="test_res", title="Test Resource") assert get_display_name(resource_with_title) == "Test Resource" - prompt = Prompt(name="test_prompt", uri="prompt://test_prompt") + prompt = Prompt(name="test_prompt", uri=f"{PROMPT_SCHEME}/test_prompt") assert get_display_name(prompt) == "test_prompt" - prompt_with_title = Prompt(name="test_prompt", uri="prompt://test_prompt", title="Test Prompt") + prompt_with_title = Prompt(name="test_prompt", uri=f"{PROMPT_SCHEME}/test_prompt", title="Test Prompt") assert get_display_name(prompt_with_title) == "Test Prompt" template = ResourceTemplate(uriTemplate="file://{id}", name="test_template") diff --git a/tests/server/fastmcp/test_tool_manager.py b/tests/server/fastmcp/test_tool_manager.py index f357fe761..c5adeea29 100644 --- a/tests/server/fastmcp/test_tool_manager.py +++ b/tests/server/fastmcp/test_tool_manager.py @@ -12,7 +12,7 @@ from mcp.server.fastmcp.utilities.func_metadata import ArgModelBase, FuncMetadata from mcp.server.session import ServerSessionT from mcp.shared.context import LifespanContextT, RequestT -from mcp.types import TextContent, ToolAnnotations +from mcp.types import TOOL_SCHEME, TextContent, ToolAnnotations class TestAddTools: @@ -178,6 +178,79 @@ def f(x: int) -> int: manager.add_tool(f) assert "Tool already exists: f" not in caplog.text + def test_list_tools_with_prefix(self): + """Test listing tools with prefix filtering.""" + manager = ToolManager() + + # Add tools with different URI prefixes + def math_add(a: int, b: int) -> int: + return a + b + + def math_multiply(a: int, b: int) -> int: + return a * b + + def string_concat(a: str, b: str) -> str: + return a + b + + def string_upper(text: str) -> str: + return text.upper() + + # Add tools with custom URIs + math_add_tool = Tool.from_function(math_add) + math_add_tool.uri = f"{TOOL_SCHEME}/math/add" + + math_multiply_tool = Tool.from_function(math_multiply) + math_multiply_tool.uri = f"{TOOL_SCHEME}/math/multiply" + + string_concat_tool = Tool.from_function(string_concat) + string_concat_tool.uri = f"{TOOL_SCHEME}/string/concat" + + string_upper_tool = Tool.from_function(string_upper) + string_upper_tool.uri = f"{TOOL_SCHEME}/string/upper" + + manager._tools = { + str(math_add_tool.uri): math_add_tool, + str(math_multiply_tool.uri): math_multiply_tool, + str(string_concat_tool.uri): string_concat_tool, + str(string_upper_tool.uri): string_upper_tool, + } + + # Test listing all tools + all_tools = manager.list_tools() + assert len(all_tools) == 4 + + # Test prefix filtering - math tools + math_tools = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/") + assert len(math_tools) == 2 + assert all(str(t.uri).startswith(f"{TOOL_SCHEME}/math/") for t in math_tools) + assert math_add_tool in math_tools + assert math_multiply_tool in math_tools + + # Test prefix filtering - string tools + string_tools = manager.list_tools(prefix=f"{TOOL_SCHEME}/string/") + assert len(string_tools) == 2 + assert all(str(t.uri).startswith(f"{TOOL_SCHEME}/string/") for t in string_tools) + assert string_concat_tool in string_tools + assert string_upper_tool in string_tools + + # Test exact URI match + add_tools = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/add") + assert len(add_tools) == 1 + assert add_tools[0] == math_add_tool + + # Test partial prefix doesn't match + no_partial = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/a") + assert len(no_partial) == 0 # Won't match because next char is 'd' not a separator + + # Test no matches + no_matches = manager.list_tools(prefix=f"{TOOL_SCHEME}/nonexistent") + assert len(no_matches) == 0 + + # Test with trailing slash + math_tools_slash = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/") + assert len(math_tools_slash) == 2 + assert math_tools_slash == math_tools + class TestCallTools: @pytest.mark.anyio @@ -258,6 +331,60 @@ async def test_call_unknown_tool(self): with pytest.raises(ToolError): await manager.call_tool("unknown", {"a": 1}) + @pytest.mark.anyio + async def test_call_tool_by_uri(self): + """Test calling tools by their URI instead of name.""" + + def math_add(a: int, b: int) -> int: + return a + b + + def math_multiply(a: int, b: int) -> int: + return a * b + + manager = ToolManager() + + # Add tool with default URI + manager.add_tool(math_add) + + # Add tool with custom URI + multiply_tool = Tool.from_function(math_multiply) + multiply_tool.uri = f"{TOOL_SCHEME}/custom/math/multiply" + manager._tools[str(multiply_tool.uri)] = multiply_tool + + # Call by default URI (tool://function_name) + result = await manager.call_tool(f"{TOOL_SCHEME}/math_add", {"a": 5, "b": 3}) + assert result == 8 + + # Call by custom URI + result = await manager.call_tool(f"{TOOL_SCHEME}/custom/math/multiply", {"a": 4, "b": 7}) + assert result == 28 + + # Should still work with name + result = await manager.call_tool("math_add", {"a": 2, "b": 2}) + assert result == 4 + + def test_get_tool_by_uri(self): + """Test getting tools by their URI.""" + + def calculator() -> str: + return "calculator" + + manager = ToolManager() + + # Add tool with default URI + manager.add_tool(calculator) + + # Get by name + tool = manager.get_tool("calculator") + assert tool is not None + assert tool.name == "calculator" + + # Get by URI + tool_by_uri = manager.get_tool(f"{TOOL_SCHEME}/calculator") + assert tool_by_uri is not None + assert tool_by_uri.name == "calculator" + assert tool_by_uri == tool + @pytest.mark.anyio async def test_call_tool_with_list_int_input(self): def sum_vals(vals: list[int]) -> int: diff --git a/tests/server/fastmcp/test_uri_utils.py b/tests/server/fastmcp/test_uri_utils.py new file mode 100644 index 000000000..c6ebbac5c --- /dev/null +++ b/tests/server/fastmcp/test_uri_utils.py @@ -0,0 +1,180 @@ +"""Tests for URI utility functions.""" + +from mcp.server.fastmcp.uri_utils import ( + filter_by_prefix, + normalize_to_prompt_uri, + normalize_to_tool_uri, + normalize_to_uri, +) +from mcp.types import PROMPT_SCHEME, TOOL_SCHEME + + +class TestNormalizeToUri: + """Test the generic normalize_to_uri function.""" + + def test_normalize_name_to_uri(self): + """Test converting a name to URI.""" + result = normalize_to_uri("test_name", TOOL_SCHEME) + assert result == f"{TOOL_SCHEME}/test_name" + + def test_normalize_already_uri(self): + """Test that URIs are returned unchanged.""" + uri = f"{TOOL_SCHEME}/existing_uri" + result = normalize_to_uri(uri, TOOL_SCHEME) + assert result == uri + + def test_normalize_with_different_scheme(self): + """Test normalizing with different schemes.""" + result = normalize_to_uri("test", PROMPT_SCHEME) + assert result == f"{PROMPT_SCHEME}/test" + + def test_normalize_empty_name(self): + """Test normalizing empty string.""" + result = normalize_to_uri("", TOOL_SCHEME) + assert result == f"{TOOL_SCHEME}/" + + def test_normalize_special_characters(self): + """Test normalizing names with special characters.""" + result = normalize_to_uri("test-name_123", TOOL_SCHEME) + assert result == f"{TOOL_SCHEME}/test-name_123" + + +class TestNormalizeToToolUri: + """Test the tool-specific URI normalization.""" + + def test_normalize_tool_name(self): + """Test converting tool name to URI.""" + result = normalize_to_tool_uri("calculator") + assert result == f"{TOOL_SCHEME}/calculator" + + def test_normalize_existing_tool_uri(self): + """Test that tool URIs are returned unchanged.""" + uri = f"{TOOL_SCHEME}/existing_tool" + result = normalize_to_tool_uri(uri) + assert result == uri + + def test_normalize_tool_with_path(self): + """Test normalizing tool names that look like paths.""" + result = normalize_to_tool_uri("math/calculator") + assert result == f"{TOOL_SCHEME}/math/calculator" + + +class TestNormalizeToPromptUri: + """Test the prompt-specific URI normalization.""" + + def test_normalize_prompt_name(self): + """Test converting prompt name to URI.""" + result = normalize_to_prompt_uri("greeting") + assert result == f"{PROMPT_SCHEME}/greeting" + + def test_normalize_existing_prompt_uri(self): + """Test that prompt URIs are returned unchanged.""" + uri = f"{PROMPT_SCHEME}/existing_prompt" + result = normalize_to_prompt_uri(uri) + assert result == uri + + def test_normalize_prompt_with_path(self): + """Test normalizing prompt names that look like paths.""" + result = normalize_to_prompt_uri("templates/greeting") + assert result == f"{PROMPT_SCHEME}/templates/greeting" + + +class TestFilterByPrefix: + """Test the prefix filtering function.""" + + def test_filter_no_prefix(self): + """Test that no prefix returns all items.""" + items = ["item1", "item2", "item3"] + result = filter_by_prefix(items, None, lambda x: x) + assert result == items + + def test_filter_with_prefix(self): + """Test filtering with a prefix.""" + items = [f"{TOOL_SCHEME}/math/add", f"{TOOL_SCHEME}/math/subtract", f"{TOOL_SCHEME}/string/concat"] + result = filter_by_prefix(items, f"{TOOL_SCHEME}/math", lambda x: x) + assert len(result) == 2 + assert f"{TOOL_SCHEME}/math/add" in result + assert f"{TOOL_SCHEME}/math/subtract" in result + + def test_filter_prefix_without_slash(self): + """Test that prefix without trailing slash only matches at boundaries.""" + items = [ + f"{TOOL_SCHEME}/math/add", + f"{TOOL_SCHEME}/math/subtract", + f"{TOOL_SCHEME}/string/concat", + f"{TOOL_SCHEME}/mathematic", + ] + result = filter_by_prefix(items, f"{TOOL_SCHEME}/math", lambda x: x) + assert len(result) == 2 # Matches because next char is '/' + assert f"{TOOL_SCHEME}/math/add" in result + assert f"{TOOL_SCHEME}/math/subtract" in result + assert f"{TOOL_SCHEME}/mathematic" not in result # Doesn't match because next char is 'e' + + # With trailing slash also matches + result_with_slash = filter_by_prefix(items, f"{TOOL_SCHEME}/math/", lambda x: x) + assert len(result_with_slash) == 2 + assert result_with_slash == result + + def test_filter_with_trailing_slash(self): + """Test filtering when prefix already has trailing slash.""" + items = [f"{PROMPT_SCHEME}/greet/hello", f"{PROMPT_SCHEME}/greet/goodbye", f"{PROMPT_SCHEME}/chat/start"] + result = filter_by_prefix(items, f"{PROMPT_SCHEME}/greet/", lambda x: x) + assert len(result) == 2 + assert f"{PROMPT_SCHEME}/greet/hello" in result + assert f"{PROMPT_SCHEME}/greet/goodbye" in result + + def test_filter_empty_list(self): + """Test filtering empty list.""" + items = [] + result = filter_by_prefix(items, "any://prefix", lambda x: x) + assert result == [] + + def test_filter_no_matches(self): + """Test filtering when no items match.""" + items = [f"{TOOL_SCHEME}/math/add", f"{TOOL_SCHEME}/math/subtract"] + result = filter_by_prefix(items, f"{TOOL_SCHEME}/string", lambda x: x) + assert result == [] + + def test_filter_with_objects(self): + """Test filtering objects using a URI getter function.""" + + class MockTool: + def __init__(self, uri): + self.uri = uri + + tools = [ + MockTool(f"{TOOL_SCHEME}/math/add"), + MockTool(f"{TOOL_SCHEME}/math/multiply"), + MockTool(f"{TOOL_SCHEME}/string/concat"), + ] + + result = filter_by_prefix(tools, f"{TOOL_SCHEME}/math", lambda t: t.uri) + assert len(result) == 2 + assert result[0].uri == f"{TOOL_SCHEME}/math/add" + assert result[1].uri == f"{TOOL_SCHEME}/math/multiply" + + def test_filter_case_sensitive(self): + """Test that filtering is case sensitive.""" + items = [f"{TOOL_SCHEME}/Math/add", f"{TOOL_SCHEME}/math/add"] + result = filter_by_prefix(items, f"{TOOL_SCHEME}/math", lambda x: x) + assert len(result) == 1 + assert f"{TOOL_SCHEME}/math/add" in result + + def test_filter_exact_prefix_match(self): + """Test that exact prefix matches work correctly.""" + items = [f"{TOOL_SCHEME}/test", f"{TOOL_SCHEME}/test/sub", f"{TOOL_SCHEME}/testing"] + result = filter_by_prefix(items, f"{TOOL_SCHEME}/test", lambda x: x) + # Should match "tool:/test" (exact) and "tool:/test/sub" but not "tool:/testing" + assert len(result) == 2 + assert f"{TOOL_SCHEME}/test" in result + assert f"{TOOL_SCHEME}/test/sub" in result + assert f"{TOOL_SCHEME}/testing" not in result + + def test_filter_root_prefix(self): + """Test filtering with just the scheme as prefix.""" + items = [f"{TOOL_SCHEME}/add", f"{TOOL_SCHEME}/subtract", f"{PROMPT_SCHEME}/greet"] + result = filter_by_prefix(items, f"{TOOL_SCHEME}/", lambda x: x) + assert len(result) == 2 + assert f"{TOOL_SCHEME}/add" in result + assert f"{TOOL_SCHEME}/subtract" in result + assert f"{PROMPT_SCHEME}/greet" not in result diff --git a/tests/server/test_cancel_handling.py b/tests/server/test_cancel_handling.py index e649e7c01..a42803468 100644 --- a/tests/server/test_cancel_handling.py +++ b/tests/server/test_cancel_handling.py @@ -8,6 +8,7 @@ from mcp.shared.exceptions import McpError from mcp.shared.memory import create_connected_server_and_client_session from mcp.types import ( + TOOL_SCHEME, CallToolRequest, CallToolRequestParams, CallToolResult, @@ -34,7 +35,7 @@ async def test_server_remains_functional_after_cancel(): async def handle_list_tools(request) -> list[Tool]: return [ Tool( - uri="tool://test_tool", + uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="Tool for testing", inputSchema={}, diff --git a/tests/server/test_lowlevel_input_validation.py b/tests/server/test_lowlevel_input_validation.py index 96bfd4cd8..9467fe423 100644 --- a/tests/server/test_lowlevel_input_validation.py +++ b/tests/server/test_lowlevel_input_validation.py @@ -14,7 +14,7 @@ from mcp.server.session import ServerSession from mcp.shared.message import SessionMessage from mcp.shared.session import RequestResponder -from mcp.types import CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool +from mcp.types import TOOL_SCHEME, CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool async def run_tool_test( @@ -99,7 +99,7 @@ async def handle_messages(): def create_add_tool() -> Tool: """Create a standard 'add' tool for testing.""" return Tool( - uri="tool://add", + uri=f"{TOOL_SCHEME}/add", name="add", description="Add two numbers", inputSchema={ @@ -190,7 +190,7 @@ async def test_cache_refresh_on_missing_tool(): """Test that tool cache is refreshed when tool is not found.""" tools = [ Tool( - uri="tool://multiply", + uri=f"{TOOL_SCHEME}/multiply", name="multiply", description="Multiply two numbers", inputSchema={ @@ -232,7 +232,7 @@ async def test_enum_constraint_validation(): """Test that enum constraints are validated.""" tools = [ Tool( - uri="tool://greet", + uri=f"{TOOL_SCHEME}/greet", name="greet", description="Greet someone", inputSchema={ @@ -270,7 +270,7 @@ async def test_tool_not_in_list_logs_warning(caplog): """Test that calling a tool not in list_tools logs a warning and skips validation.""" tools = [ Tool( - uri="tool://add", + uri=f"{TOOL_SCHEME}/add", name="add", description="Add two numbers", inputSchema={ diff --git a/tests/server/test_lowlevel_output_validation.py b/tests/server/test_lowlevel_output_validation.py index ee5040993..cf19ece27 100644 --- a/tests/server/test_lowlevel_output_validation.py +++ b/tests/server/test_lowlevel_output_validation.py @@ -14,7 +14,7 @@ from mcp.server.session import ServerSession from mcp.shared.message import SessionMessage from mcp.shared.session import RequestResponder -from mcp.types import CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool +from mcp.types import TOOL_SCHEME, CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool async def run_tool_test( @@ -101,7 +101,7 @@ async def test_content_only_without_output_schema(): """Test returning content only when no outputSchema is defined.""" tools = [ Tool( - uri="tool://echo", + uri=f"{TOOL_SCHEME}/echo", name="echo", description="Echo a message", inputSchema={ @@ -141,7 +141,7 @@ async def test_dict_only_without_output_schema(): """Test returning dict only when no outputSchema is defined.""" tools = [ Tool( - uri="tool://get_info", + uri=f"{TOOL_SCHEME}/get_info", name="get_info", description="Get structured information", inputSchema={ @@ -179,7 +179,7 @@ async def test_both_content_and_dict_without_output_schema(): """Test returning both content and dict when no outputSchema is defined.""" tools = [ Tool( - uri="tool://process", + uri=f"{TOOL_SCHEME}/process", name="process", description="Process data", inputSchema={ @@ -218,7 +218,7 @@ async def test_content_only_with_output_schema_error(): """Test error when outputSchema is defined but only content is returned.""" tools = [ Tool( - uri="tool://structured_tool", + uri=f"{TOOL_SCHEME}/structured_tool", name="structured_tool", description="Tool expecting structured output", inputSchema={ @@ -258,7 +258,7 @@ async def test_valid_dict_with_output_schema(): """Test valid dict output matching outputSchema.""" tools = [ Tool( - uri="tool://calc", + uri=f"{TOOL_SCHEME}/calc", name="calc", description="Calculate result", inputSchema={ @@ -308,7 +308,7 @@ async def test_invalid_dict_with_output_schema(): """Test dict output that doesn't match outputSchema.""" tools = [ Tool( - uri="tool://user_info", + uri=f"{TOOL_SCHEME}/user_info", name="user_info", description="Get user information", inputSchema={ @@ -353,7 +353,7 @@ async def test_both_content_and_valid_dict_with_output_schema(): """Test returning both content and valid dict with outputSchema.""" tools = [ Tool( - uri="tool://analyze", + uri=f"{TOOL_SCHEME}/analyze", name="analyze", description="Analyze data", inputSchema={ @@ -401,7 +401,7 @@ async def test_output_schema_type_validation(): """Test outputSchema validates types correctly.""" tools = [ Tool( - uri="tool://stats", + uri=f"{TOOL_SCHEME}/stats", name="stats", description="Get statistics", inputSchema={ diff --git a/tests/server/test_lowlevel_tool_annotations.py b/tests/server/test_lowlevel_tool_annotations.py index 525ceaa1d..6f2a6ee3a 100644 --- a/tests/server/test_lowlevel_tool_annotations.py +++ b/tests/server/test_lowlevel_tool_annotations.py @@ -10,7 +10,7 @@ from mcp.server.session import ServerSession from mcp.shared.message import SessionMessage from mcp.shared.session import RequestResponder -from mcp.types import ClientResult, ServerNotification, ServerRequest, Tool, ToolAnnotations +from mcp.types import TOOL_SCHEME, ClientResult, ServerNotification, ServerRequest, Tool, ToolAnnotations @pytest.mark.anyio @@ -23,7 +23,7 @@ async def test_lowlevel_server_tool_annotations(): async def list_tools(request): return [ Tool( - uri="tool://echo", + uri=f"{TOOL_SCHEME}/echo", name="echo", description="Echo a message back", inputSchema={ diff --git a/tests/server/test_session.py b/tests/server/test_session.py index e10a51b4d..2976bcaa5 100644 --- a/tests/server/test_session.py +++ b/tests/server/test_session.py @@ -16,6 +16,7 @@ CompletionContext, CompletionsCapability, InitializedNotification, + ListPromptsRequest, PromptReference, PromptsCapability, ResourcesCapability, @@ -90,7 +91,7 @@ async def test_server_capabilities(): # Add a prompts handler @server.list_prompts() - async def list_prompts(): + async def list_prompts(request: ListPromptsRequest): return [] caps = server.get_capabilities(notification_options, experimental_capabilities) diff --git a/tests/shared/test_progress_notifications.py b/tests/shared/test_progress_notifications.py index 5a08e8004..7a53638a8 100644 --- a/tests/shared/test_progress_notifications.py +++ b/tests/shared/test_progress_notifications.py @@ -16,6 +16,7 @@ RequestResponder, SessionMessage, ) +from mcp.types import TOOL_SCHEME @pytest.mark.anyio @@ -79,7 +80,7 @@ async def handle_progress( async def handle_list_tools(request) -> list[types.Tool]: return [ types.Tool( - uri="tool://test_tool", + uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A tool that sends progress notifications list: async def handle_list_tools(request) -> list[types.Tool]: return [ types.Tool( - uri="tool://slow_tool", + uri=f"{TOOL_SCHEME}/slow_tool", name="slow_tool", description="A slow tool that takes 10 seconds to complete", inputSchema={}, diff --git a/tests/shared/test_sse.py b/tests/shared/test_sse.py index 494c02165..1219c05ed 100644 --- a/tests/shared/test_sse.py +++ b/tests/shared/test_sse.py @@ -23,6 +23,7 @@ from mcp.server.transport_security import TransportSecuritySettings from mcp.shared.exceptions import McpError from mcp.types import ( + TOOL_SCHEME, EmptyResult, ErrorData, InitializeResult, @@ -67,7 +68,7 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: async def handle_list_tools(request) -> list[Tool]: return [ Tool( - uri="tool://test_tool", + uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, @@ -327,13 +328,13 @@ async def handle_call_tool(name: str, args: dict) -> list[TextContent]: async def handle_list_tools(request) -> list[Tool]: return [ Tool( - uri="tool://echo_headers", + uri=f"{TOOL_SCHEME}/echo_headers", name="echo_headers", description="Echoes request headers", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri="tool://echo_context", + uri=f"{TOOL_SCHEME}/echo_context", name="echo_context", description="Echoes request context", inputSchema={ diff --git a/tests/shared/test_streamable_http.py b/tests/shared/test_streamable_http.py index 05dfbabf5..f6dc3ffe9 100644 --- a/tests/shared/test_streamable_http.py +++ b/tests/shared/test_streamable_http.py @@ -45,6 +45,7 @@ ) from mcp.shared.session import RequestResponder from mcp.types import ( + TOOL_SCHEME, InitializeResult, TextContent, TextResourceContents, @@ -141,37 +142,37 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: async def handle_list_tools(request) -> list[Tool]: return [ Tool( - uri="tool://test_tool", + uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri="tool://test_tool_with_standalone_notification", + uri=f"{TOOL_SCHEME}/test_tool_with_standalone_notification", name="test_tool_with_standalone_notification", description="A test tool that sends a notification", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri="tool://long_running_with_checkpoints", + uri=f"{TOOL_SCHEME}/long_running_with_checkpoints", name="long_running_with_checkpoints", description="A long-running tool that sends periodic notifications", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri="tool://test_sampling_tool", + uri=f"{TOOL_SCHEME}/test_sampling_tool", name="test_sampling_tool", description="A tool that triggers server-side sampling", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri="tool://wait_for_lock_with_notification", + uri=f"{TOOL_SCHEME}/wait_for_lock_with_notification", name="wait_for_lock_with_notification", description="A tool that sends a notification and waits for lock", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri="tool://release_lock", + uri=f"{TOOL_SCHEME}/release_lock", name="release_lock", description="A tool that releases the lock", inputSchema={"type": "object", "properties": {}}, @@ -1286,13 +1287,13 @@ def __init__(self): async def handle_list_tools(request) -> list[Tool]: return [ Tool( - uri="tool://echo_headers", + uri=f"{TOOL_SCHEME}/echo_headers", name="echo_headers", description="Echo request headers from context", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri="tool://echo_context", + uri=f"{TOOL_SCHEME}/echo_context", name="echo_context", description="Echo request context with custom data", inputSchema={ diff --git a/tests/shared/test_ws.py b/tests/shared/test_ws.py index 7e0d8d208..10ed45078 100644 --- a/tests/shared/test_ws.py +++ b/tests/shared/test_ws.py @@ -16,6 +16,7 @@ from mcp.server.websocket import websocket_server from mcp.shared.exceptions import McpError from mcp.types import ( + TOOL_SCHEME, EmptyResult, ErrorData, InitializeResult, @@ -60,7 +61,7 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: async def handle_list_tools(request) -> list[Tool]: return [ Tool( - uri="tool://test_tool", + uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, diff --git a/tests/test_types.py b/tests/test_types.py index 5366ec4dc..9df98f8e6 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -1,7 +1,10 @@ import pytest +from pydantic import AnyUrl from mcp.types import ( LATEST_PROTOCOL_VERSION, + PROMPT_SCHEME, + TOOL_SCHEME, ClientRequest, Implementation, JSONRPCMessage, @@ -48,27 +51,27 @@ def test_resource_uri(): """Test that Resource requires URI and validates scheme.""" # Resource should require URI with pytest.raises(ValueError): - Resource(name="test") + Resource(name="test") # pyright: ignore[reportCallIssue] # This should work - resource = Resource(name="test", uri="file://test.txt") + resource = Resource(name="test", uri=AnyUrl("file://test.txt")) assert resource.name == "test" assert str(resource.uri) == "file://test.txt/" # AnyUrl adds trailing slash # Should reject tool:// and prompt:// schemes with pytest.raises(ValueError, match="reserved schemes"): - Resource(name="test", uri="tool://test") + Resource(name="test", uri=AnyUrl(f"{TOOL_SCHEME}/test")) with pytest.raises(ValueError, match="reserved schemes"): - Resource(name="test", uri="prompt://test") + Resource(name="test", uri=AnyUrl(f"{PROMPT_SCHEME}/test")) def test_tool_uri_validation(): """Test that Tool requires URI with tool scheme.""" # Tool requires URI with tool:// scheme - tool = Tool(name="calculator", inputSchema={"type": "object"}, uri="tool://calculator") + tool = Tool(name="calculator", inputSchema={"type": "object"}, uri=f"{TOOL_SCHEME}/calculator") assert tool.name == "calculator" - assert str(tool.uri) == "tool://calculator" + assert str(tool.uri) == f"{TOOL_SCHEME}/calculator" # Should reject non-tool schemes with pytest.raises(ValueError): @@ -78,9 +81,9 @@ def test_tool_uri_validation(): def test_prompt_uri_validation(): """Test that Prompt requires URI with prompt scheme.""" # Prompt requires URI with prompt:// scheme - prompt = Prompt(name="greeting", uri="prompt://greeting") + prompt = Prompt(name="greeting", uri=f"{PROMPT_SCHEME}/greeting") assert prompt.name == "greeting" - assert str(prompt.uri) == "prompt://greeting" + assert str(prompt.uri) == f"{PROMPT_SCHEME}/greeting" # Should reject non-prompt schemes with pytest.raises(ValueError): From 8238b0a92b1e8433812c6bade167a2b8391e4e76 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sat, 2 Aug 2025 16:26:41 -0700 Subject: [PATCH 09/15] refactor: clean up unnecessary changes in tests and examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace unused request parameters with _ in handler functions - Remove explicit URI additions where auto-generation suffices - Remove unused TOOL_SCHEME and other imports - Keep only changes essential for prefix filtering functionality This reduces noise in tests and examples while maintaining the core functionality of URI-based storage and prefix filtering. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../simple-prompt/mcp_simple_prompt/server.py | 2 +- .../mcp_simple_resource/server.py | 4 +--- .../server.py | 2 +- .../mcp_simple_streamablehttp/server.py | 2 +- .../simple-tool/mcp_simple_tool/server.py | 2 +- examples/servers/structured_output_lowlevel.py | 2 +- examples/snippets/servers/lowlevel/basic.py | 2 +- examples/snippets/servers/lowlevel/lifespan.py | 2 +- .../servers/lowlevel/structured_output.py | 2 +- tests/client/test_output_schema_validation.py | 16 ++++++---------- tests/client/test_session_group.py | 5 +---- tests/issues/test_152_resource_mime_type.py | 2 +- tests/issues/test_88_random_error.py | 6 ++---- tests/server/test_cancel_handling.py | 4 +--- tests/server/test_lowlevel_input_validation.py | 2 +- tests/server/test_lowlevel_output_validation.py | 12 ++---------- tests/server/test_lowlevel_tool_annotations.py | 5 ++--- tests/server/test_session.py | 5 ++--- tests/shared/test_memory.py | 3 +-- tests/shared/test_progress_notifications.py | 4 +--- tests/shared/test_session.py | 4 +--- tests/shared/test_sse.py | 8 ++------ tests/shared/test_streamable_http.py | 7 ++----- tests/shared/test_ws.py | 4 +--- 24 files changed, 35 insertions(+), 72 deletions(-) diff --git a/examples/servers/simple-prompt/mcp_simple_prompt/server.py b/examples/servers/simple-prompt/mcp_simple_prompt/server.py index 4ffcf09a9..e62c66f42 100644 --- a/examples/servers/simple-prompt/mcp_simple_prompt/server.py +++ b/examples/servers/simple-prompt/mcp_simple_prompt/server.py @@ -49,7 +49,7 @@ def main(port: int, transport: str) -> int: app = Server("mcp-simple-prompt") @app.list_prompts() - async def list_prompts(request: types.ListPromptsRequest) -> list[types.Prompt]: + async def list_prompts(_) -> list[types.Prompt]: return [ types.Prompt( name="simple", diff --git a/examples/servers/simple-resource/mcp_simple_resource/server.py b/examples/servers/simple-resource/mcp_simple_resource/server.py index 57fc60b69..43bcaba5b 100644 --- a/examples/servers/simple-resource/mcp_simple_resource/server.py +++ b/examples/servers/simple-resource/mcp_simple_resource/server.py @@ -32,9 +32,7 @@ def main(port: int, transport: str) -> int: app = Server("mcp-simple-resource") @app.list_resources() - async def list_resources( - request: types.ListResourcesRequest, - ) -> list[types.Resource]: + async def list_resources(_) -> list[types.Resource]: return [ types.Resource( uri=FileUrl(f"file:///{name}.txt"), diff --git a/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py b/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py index 330f683b1..b5da75c05 100644 --- a/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py +++ b/examples/servers/simple-streamablehttp-stateless/mcp_simple_streamablehttp_stateless/server.py @@ -69,7 +69,7 @@ async def call_tool(name: str, arguments: dict) -> list[types.ContentBlock]: ] @app.list_tools() - async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: + async def list_tools(_) -> list[types.Tool]: return [ types.Tool( name="start-notification-stream", diff --git a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py index 1d9ee02f8..b69f8071b 100644 --- a/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py +++ b/examples/servers/simple-streamablehttp/mcp_simple_streamablehttp/server.py @@ -87,7 +87,7 @@ async def call_tool(name: str, arguments: dict) -> list[types.ContentBlock]: ] @app.list_tools() - async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: + async def list_tools(_) -> list[types.Tool]: return [ types.Tool( name="start-notification-stream", diff --git a/examples/servers/simple-tool/mcp_simple_tool/server.py b/examples/servers/simple-tool/mcp_simple_tool/server.py index 9846a20cf..d7ac21c8d 100644 --- a/examples/servers/simple-tool/mcp_simple_tool/server.py +++ b/examples/servers/simple-tool/mcp_simple_tool/server.py @@ -37,7 +37,7 @@ async def fetch_tool(name: str, arguments: dict) -> list[types.ContentBlock]: return await fetch_website(arguments["url"]) @app.list_tools() - async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: + async def list_tools(_) -> list[types.Tool]: return [ types.Tool( name="fetch", diff --git a/examples/servers/structured_output_lowlevel.py b/examples/servers/structured_output_lowlevel.py index a678f7595..db57f958a 100644 --- a/examples/servers/structured_output_lowlevel.py +++ b/examples/servers/structured_output_lowlevel.py @@ -21,7 +21,7 @@ @server.list_tools() -async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: +async def list_tools(_) -> list[types.Tool]: """List available tools with their schemas.""" return [ types.Tool( diff --git a/examples/snippets/servers/lowlevel/basic.py b/examples/snippets/servers/lowlevel/basic.py index 6d494a134..bbdc1d63e 100644 --- a/examples/snippets/servers/lowlevel/basic.py +++ b/examples/snippets/servers/lowlevel/basic.py @@ -15,7 +15,7 @@ @server.list_prompts() -async def handle_list_prompts(request: types.ListPromptsRequest) -> list[types.Prompt]: +async def handle_list_prompts(_) -> list[types.Prompt]: """List available prompts.""" return [ types.Prompt( diff --git a/examples/snippets/servers/lowlevel/lifespan.py b/examples/snippets/servers/lowlevel/lifespan.py index 947ce09fa..652ac4754 100644 --- a/examples/snippets/servers/lowlevel/lifespan.py +++ b/examples/snippets/servers/lowlevel/lifespan.py @@ -49,7 +49,7 @@ async def server_lifespan(_server: Server) -> AsyncIterator[dict]: @server.list_tools() -async def handle_list_tools(request: types.ListToolsRequest) -> list[types.Tool]: +async def handle_list_tools(_) -> list[types.Tool]: """List available tools.""" return [ types.Tool( diff --git a/examples/snippets/servers/lowlevel/structured_output.py b/examples/snippets/servers/lowlevel/structured_output.py index af725e2a9..9e25cfd42 100644 --- a/examples/snippets/servers/lowlevel/structured_output.py +++ b/examples/snippets/servers/lowlevel/structured_output.py @@ -15,7 +15,7 @@ @server.list_tools() -async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: +async def list_tools(_) -> list[types.Tool]: """List available tools with structured output schemas.""" return [ types.Tool( diff --git a/tests/client/test_output_schema_validation.py b/tests/client/test_output_schema_validation.py index c3b1b256c..6a3a4d98b 100644 --- a/tests/client/test_output_schema_validation.py +++ b/tests/client/test_output_schema_validation.py @@ -8,7 +8,7 @@ from mcp.shared.memory import ( create_connected_server_and_client_session as client_session, ) -from mcp.types import TOOL_SCHEME, Tool +from mcp.types import Tool @contextmanager @@ -42,10 +42,9 @@ async def test_tool_structured_output_client_side_validation_basemodel(self): } @server.list_tools() - async def list_tools(request): + async def list_tools(_): return [ Tool( - uri=f"{TOOL_SCHEME}/get_user", name="get_user", description="Get user data", inputSchema={"type": "object"}, @@ -82,10 +81,9 @@ async def test_tool_structured_output_client_side_validation_primitive(self): } @server.list_tools() - async def list_tools(request): + async def list_tools(_): return [ Tool( - uri=f"{TOOL_SCHEME}/calculate", name="calculate", description="Calculate something", inputSchema={"type": "object"}, @@ -114,10 +112,9 @@ async def test_tool_structured_output_client_side_validation_dict_typed(self): output_schema = {"type": "object", "additionalProperties": {"type": "integer"}, "title": "get_scores_Output"} @server.list_tools() - async def list_tools(request): + async def list_tools(_): return [ Tool( - uri=f"{TOOL_SCHEME}/get_scores", name="get_scores", description="Get scores", inputSchema={"type": "object"}, @@ -150,10 +147,9 @@ async def test_tool_structured_output_client_side_validation_missing_required(se } @server.list_tools() - async def list_tools(request): + async def list_tools(_): return [ Tool( - uri=f"{TOOL_SCHEME}/get_person", name="get_person", description="Get person data", inputSchema={"type": "object"}, @@ -179,7 +175,7 @@ async def test_tool_not_listed_warning(self, caplog): server = Server("test-server") @server.list_tools() - async def list_tools(request): + async def list_tools(_): # Return empty list - tool is not listed return [] diff --git a/tests/client/test_session_group.py b/tests/client/test_session_group.py index f5a3ced24..16a887e00 100644 --- a/tests/client/test_session_group.py +++ b/tests/client/test_session_group.py @@ -12,7 +12,6 @@ ) from mcp.client.stdio import StdioServerParameters from mcp.shared.exceptions import McpError -from mcp.types import TOOL_SCHEME @pytest.fixture @@ -59,9 +58,7 @@ def hook(name, server_info): return f"{(server_info.name)}-{name}" mcp_session_group = ClientSessionGroup(component_name_hook=hook) - mcp_session_group._tools = { - "server1-my_tool": types.Tool(uri=f"{TOOL_SCHEME}/my_tool", name="my_tool", inputSchema={}) - } + mcp_session_group._tools = {"server1-my_tool": types.Tool(name="my_tool", inputSchema={})} mcp_session_group._tool_to_session = {"server1-my_tool": mock_session} text_content = types.TextContent(type="text", text="OK") mock_session.call_tool.return_value = types.CallToolResult(content=[text_content]) diff --git a/tests/issues/test_152_resource_mime_type.py b/tests/issues/test_152_resource_mime_type.py index 6e9036174..8960c1376 100644 --- a/tests/issues/test_152_resource_mime_type.py +++ b/tests/issues/test_152_resource_mime_type.py @@ -79,7 +79,7 @@ async def test_lowlevel_resource_mime_type(): ] @server.list_resources() - async def handle_list_resources(request: types.ListResourcesRequest): + async def handle_list_resources(_): return test_resources @server.read_resource() diff --git a/tests/issues/test_88_random_error.py b/tests/issues/test_88_random_error.py index 30e23d555..8457aa9c1 100644 --- a/tests/issues/test_88_random_error.py +++ b/tests/issues/test_88_random_error.py @@ -12,7 +12,7 @@ from mcp.client.session import ClientSession from mcp.server.lowlevel import Server from mcp.shared.exceptions import McpError -from mcp.types import TOOL_SCHEME, ContentBlock, TextContent +from mcp.types import ContentBlock, TextContent @pytest.mark.anyio @@ -31,16 +31,14 @@ async def test_notification_validation_error(tmp_path: Path): slow_request_lock = anyio.Event() @server.list_tools() - async def list_tools(request) -> list[types.Tool]: + async def list_tools(_) -> list[types.Tool]: return [ types.Tool( - uri=f"{TOOL_SCHEME}/slow", name="slow", description="A slow tool", inputSchema={"type": "object"}, ), types.Tool( - uri=f"{TOOL_SCHEME}/fast", name="fast", description="A fast tool", inputSchema={"type": "object"}, diff --git a/tests/server/test_cancel_handling.py b/tests/server/test_cancel_handling.py index a42803468..a8377d054 100644 --- a/tests/server/test_cancel_handling.py +++ b/tests/server/test_cancel_handling.py @@ -8,7 +8,6 @@ from mcp.shared.exceptions import McpError from mcp.shared.memory import create_connected_server_and_client_session from mcp.types import ( - TOOL_SCHEME, CallToolRequest, CallToolRequestParams, CallToolResult, @@ -32,10 +31,9 @@ async def test_server_remains_functional_after_cancel(): first_request_id = None @server.list_tools() - async def handle_list_tools(request) -> list[Tool]: + async def handle_list_tools(_) -> list[Tool]: return [ Tool( - uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="Tool for testing", inputSchema={}, diff --git a/tests/server/test_lowlevel_input_validation.py b/tests/server/test_lowlevel_input_validation.py index 9467fe423..be9dc2500 100644 --- a/tests/server/test_lowlevel_input_validation.py +++ b/tests/server/test_lowlevel_input_validation.py @@ -35,7 +35,7 @@ async def run_tool_test( server = Server("test") @server.list_tools() - async def list_tools(request): + async def list_tools(_): return tools @server.call_tool() diff --git a/tests/server/test_lowlevel_output_validation.py b/tests/server/test_lowlevel_output_validation.py index cf19ece27..126cd3991 100644 --- a/tests/server/test_lowlevel_output_validation.py +++ b/tests/server/test_lowlevel_output_validation.py @@ -14,7 +14,7 @@ from mcp.server.session import ServerSession from mcp.shared.message import SessionMessage from mcp.shared.session import RequestResponder -from mcp.types import TOOL_SCHEME, CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool +from mcp.types import CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool async def run_tool_test( @@ -35,7 +35,7 @@ async def run_tool_test( server = Server("test") @server.list_tools() - async def list_tools(request): + async def list_tools(_): return tools @server.call_tool() @@ -101,7 +101,6 @@ async def test_content_only_without_output_schema(): """Test returning content only when no outputSchema is defined.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/echo", name="echo", description="Echo a message", inputSchema={ @@ -141,7 +140,6 @@ async def test_dict_only_without_output_schema(): """Test returning dict only when no outputSchema is defined.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/get_info", name="get_info", description="Get structured information", inputSchema={ @@ -179,7 +177,6 @@ async def test_both_content_and_dict_without_output_schema(): """Test returning both content and dict when no outputSchema is defined.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/process", name="process", description="Process data", inputSchema={ @@ -218,7 +215,6 @@ async def test_content_only_with_output_schema_error(): """Test error when outputSchema is defined but only content is returned.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/structured_tool", name="structured_tool", description="Tool expecting structured output", inputSchema={ @@ -258,7 +254,6 @@ async def test_valid_dict_with_output_schema(): """Test valid dict output matching outputSchema.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/calc", name="calc", description="Calculate result", inputSchema={ @@ -308,7 +303,6 @@ async def test_invalid_dict_with_output_schema(): """Test dict output that doesn't match outputSchema.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/user_info", name="user_info", description="Get user information", inputSchema={ @@ -353,7 +347,6 @@ async def test_both_content_and_valid_dict_with_output_schema(): """Test returning both content and valid dict with outputSchema.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/analyze", name="analyze", description="Analyze data", inputSchema={ @@ -401,7 +394,6 @@ async def test_output_schema_type_validation(): """Test outputSchema validates types correctly.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/stats", name="stats", description="Get statistics", inputSchema={ diff --git a/tests/server/test_lowlevel_tool_annotations.py b/tests/server/test_lowlevel_tool_annotations.py index 6f2a6ee3a..fd70eaaec 100644 --- a/tests/server/test_lowlevel_tool_annotations.py +++ b/tests/server/test_lowlevel_tool_annotations.py @@ -10,7 +10,7 @@ from mcp.server.session import ServerSession from mcp.shared.message import SessionMessage from mcp.shared.session import RequestResponder -from mcp.types import TOOL_SCHEME, ClientResult, ServerNotification, ServerRequest, Tool, ToolAnnotations +from mcp.types import ClientResult, ServerNotification, ServerRequest, Tool, ToolAnnotations @pytest.mark.anyio @@ -20,10 +20,9 @@ async def test_lowlevel_server_tool_annotations(): # Create a tool with annotations @server.list_tools() - async def list_tools(request): + async def list_tools(_): return [ Tool( - uri=f"{TOOL_SCHEME}/echo", name="echo", description="Echo a message back", inputSchema={ diff --git a/tests/server/test_session.py b/tests/server/test_session.py index 2976bcaa5..d89b6ecd7 100644 --- a/tests/server/test_session.py +++ b/tests/server/test_session.py @@ -16,7 +16,6 @@ CompletionContext, CompletionsCapability, InitializedNotification, - ListPromptsRequest, PromptReference, PromptsCapability, ResourcesCapability, @@ -91,7 +90,7 @@ async def test_server_capabilities(): # Add a prompts handler @server.list_prompts() - async def list_prompts(request: ListPromptsRequest): + async def list_prompts(_): return [] caps = server.get_capabilities(notification_options, experimental_capabilities) @@ -101,7 +100,7 @@ async def list_prompts(request: ListPromptsRequest): # Add a resources handler @server.list_resources() - async def list_resources(request: types.ListResourcesRequest): + async def list_resources(_): return [] caps = server.get_capabilities(notification_options, experimental_capabilities) diff --git a/tests/shared/test_memory.py b/tests/shared/test_memory.py index b1e0c5c73..8ccb7fb7f 100644 --- a/tests/shared/test_memory.py +++ b/tests/shared/test_memory.py @@ -9,7 +9,6 @@ ) from mcp.types import ( EmptyResult, - ListResourcesRequest, Resource, ) @@ -19,7 +18,7 @@ def mcp_server() -> Server: server = Server(name="test_server") @server.list_resources() - async def handle_list_resources(request: ListResourcesRequest): + async def handle_list_resources(_): return [ Resource( uri=AnyUrl("memory://test"), diff --git a/tests/shared/test_progress_notifications.py b/tests/shared/test_progress_notifications.py index 7a53638a8..bc1bcd531 100644 --- a/tests/shared/test_progress_notifications.py +++ b/tests/shared/test_progress_notifications.py @@ -16,7 +16,6 @@ RequestResponder, SessionMessage, ) -from mcp.types import TOOL_SCHEME @pytest.mark.anyio @@ -77,10 +76,9 @@ async def handle_progress( # Register list tool handler @server.list_tools() - async def handle_list_tools(request) -> list[types.Tool]: + async def handle_list_tools(_) -> list[types.Tool]: return [ types.Tool( - uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A tool that sends progress notifications list: # Register the tool so it shows up in list_tools @server.list_tools() - async def handle_list_tools(request) -> list[types.Tool]: + async def handle_list_tools(_) -> list[types.Tool]: return [ types.Tool( - uri=f"{TOOL_SCHEME}/slow_tool", name="slow_tool", description="A slow tool that takes 10 seconds to complete", inputSchema={}, diff --git a/tests/shared/test_sse.py b/tests/shared/test_sse.py index 1219c05ed..aec9d1ee9 100644 --- a/tests/shared/test_sse.py +++ b/tests/shared/test_sse.py @@ -23,7 +23,6 @@ from mcp.server.transport_security import TransportSecuritySettings from mcp.shared.exceptions import McpError from mcp.types import ( - TOOL_SCHEME, EmptyResult, ErrorData, InitializeResult, @@ -65,10 +64,9 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: raise McpError(error=ErrorData(code=404, message="OOPS! no resource with that URI was found")) @self.list_tools() - async def handle_list_tools(request) -> list[Tool]: + async def handle_list_tools(_) -> list[Tool]: return [ Tool( - uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, @@ -325,16 +323,14 @@ async def handle_call_tool(name: str, args: dict) -> list[TextContent]: return [TextContent(type="text", text=f"Called {name}")] @self.list_tools() - async def handle_list_tools(request) -> list[Tool]: + async def handle_list_tools(_) -> list[Tool]: return [ Tool( - uri=f"{TOOL_SCHEME}/echo_headers", name="echo_headers", description="Echoes request headers", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri=f"{TOOL_SCHEME}/echo_context", name="echo_context", description="Echoes request context", inputSchema={ diff --git a/tests/shared/test_streamable_http.py b/tests/shared/test_streamable_http.py index f6dc3ffe9..8f1f14f3f 100644 --- a/tests/shared/test_streamable_http.py +++ b/tests/shared/test_streamable_http.py @@ -139,10 +139,9 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: raise ValueError(f"Unknown resource: {uri}") @self.list_tools() - async def handle_list_tools(request) -> list[Tool]: + async def handle_list_tools(_) -> list[Tool]: return [ Tool( - uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, @@ -1284,16 +1283,14 @@ def __init__(self): super().__init__("ContextAwareServer") @self.list_tools() - async def handle_list_tools(request) -> list[Tool]: + async def handle_list_tools(_) -> list[Tool]: return [ Tool( - uri=f"{TOOL_SCHEME}/echo_headers", name="echo_headers", description="Echo request headers from context", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri=f"{TOOL_SCHEME}/echo_context", name="echo_context", description="Echo request context with custom data", inputSchema={ diff --git a/tests/shared/test_ws.py b/tests/shared/test_ws.py index 10ed45078..8fd680ac1 100644 --- a/tests/shared/test_ws.py +++ b/tests/shared/test_ws.py @@ -16,7 +16,6 @@ from mcp.server.websocket import websocket_server from mcp.shared.exceptions import McpError from mcp.types import ( - TOOL_SCHEME, EmptyResult, ErrorData, InitializeResult, @@ -58,10 +57,9 @@ async def handle_read_resource(uri: AnyUrl) -> str | bytes: raise McpError(error=ErrorData(code=404, message="OOPS! no resource with that URI was found")) @self.list_tools() - async def handle_list_tools(request) -> list[Tool]: + async def handle_list_tools(_) -> list[Tool]: return [ Tool( - uri=f"{TOOL_SCHEME}/test_tool", name="test_tool", description="A test tool", inputSchema={"type": "object", "properties": {}}, From d360e8d008ed346d362372f77a2d94679a6a41fc Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sat, 2 Aug 2025 16:54:55 -0700 Subject: [PATCH 10/15] refactor: Update URI schemes and improve filter_by_prefix signature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change URI schemes from tool:// and prompt:// to mcp://tools and mcp://prompts - Add MCP_SCHEME constant and use it for URL validation - Add model validators to ensure URIs start with correct prefixes - Improve filter_by_prefix to accept AnyUrl | str, removing need for str() casts - Make Prompt description field optional (matching main branch) - Update all tests to use scheme constants instead of hardcoded values This provides a more standard URI format where 'mcp' is the scheme and 'tools'/'prompts' are path segments, while also simplifying the API. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 6 ++-- src/mcp/server/fastmcp/prompts/base.py | 2 +- src/mcp/server/fastmcp/prompts/manager.py | 2 +- .../server/fastmcp/prompts/prompt_manager.py | 2 +- .../fastmcp/resources/resource_manager.py | 2 +- src/mcp/server/fastmcp/tools/tool_manager.py | 2 +- src/mcp/server/fastmcp/uri_utils.py | 6 ++-- src/mcp/types.py | 31 ++++++++++++++----- tests/server/fastmcp/test_tool_manager.py | 6 ++-- tests/test_types.py | 6 ++-- 10 files changed, 41 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 02fbae947..2adcbba0c 100644 --- a/README.md +++ b/README.md @@ -1125,7 +1125,7 @@ server = Server("example-server", lifespan=server_lifespan) @server.list_tools() -async def handle_list_tools(request: types.ListToolsRequest) -> list[types.Tool]: +async def handle_list_tools(_) -> list[types.Tool]: """List available tools.""" return [ types.Tool( @@ -1207,7 +1207,7 @@ server = Server("example-server") @server.list_prompts() -async def handle_list_prompts(request: types.ListPromptsRequest) -> list[types.Prompt]: +async def handle_list_prompts(_) -> list[types.Prompt]: """List available prompts.""" return [ types.Prompt( @@ -1286,7 +1286,7 @@ server = Server("example-server") @server.list_tools() -async def list_tools(request: types.ListToolsRequest) -> list[types.Tool]: +async def list_tools(_) -> list[types.Tool]: """List available tools with structured output schemas.""" return [ types.Tool( diff --git a/src/mcp/server/fastmcp/prompts/base.py b/src/mcp/server/fastmcp/prompts/base.py index 2c8d296ec..e42928c94 100644 --- a/src/mcp/server/fastmcp/prompts/base.py +++ b/src/mcp/server/fastmcp/prompts/base.py @@ -60,7 +60,7 @@ class Prompt(BaseModel): name: str = Field(description="Name of the prompt") uri: str = Field(description="URI of the prompt") title: str | None = Field(None, description="Human-readable title of the prompt") - description: str = Field(description="Description of what the prompt does") + description: str | None = Field(None, description="Description of what the prompt does") arguments: list[PromptArgument] | None = Field(None, description="Arguments that can be passed to the prompt") fn: Callable[..., PromptResult | Awaitable[PromptResult]] = Field(exclude=True) diff --git a/src/mcp/server/fastmcp/prompts/manager.py b/src/mcp/server/fastmcp/prompts/manager.py index 4b0e58d43..e31291043 100644 --- a/src/mcp/server/fastmcp/prompts/manager.py +++ b/src/mcp/server/fastmcp/prompts/manager.py @@ -28,7 +28,7 @@ def get_prompt(self, name: str) -> Prompt | None: def list_prompts(self, prefix: str | None = None) -> list[Prompt]: """List all registered prompts, optionally filtered by URI prefix.""" prompts = list(self._prompts.values()) - prompts = filter_by_prefix(prompts, prefix, lambda p: str(p.uri)) + prompts = filter_by_prefix(prompts, prefix, lambda p: p.uri) logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) return prompts diff --git a/src/mcp/server/fastmcp/prompts/prompt_manager.py b/src/mcp/server/fastmcp/prompts/prompt_manager.py index 3e8e9479d..1475856f8 100644 --- a/src/mcp/server/fastmcp/prompts/prompt_manager.py +++ b/src/mcp/server/fastmcp/prompts/prompt_manager.py @@ -37,6 +37,6 @@ def get_prompt(self, name: str) -> Prompt | None: def list_prompts(self, prefix: str | None = None) -> list[Prompt]: """List all registered prompts, optionally filtered by URI prefix.""" prompts = list(self._prompts.values()) - prompts = filter_by_prefix(prompts, prefix, lambda p: str(p.uri)) + prompts = filter_by_prefix(prompts, prefix, lambda p: p.uri) logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) return prompts diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index 544e41766..de4cc1fef 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -90,7 +90,7 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: def list_resources(self, prefix: str | None = None) -> list[Resource]: """List all registered resources, optionally filtered by URI prefix.""" resources = list(self._resources.values()) - resources = filter_by_prefix(resources, prefix, lambda r: str(r.uri)) + resources = filter_by_prefix(resources, prefix, lambda r: r.uri) logger.debug("Listing resources", extra={"count": len(resources), "prefix": prefix}) return resources diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index db21bf964..f1c3d922c 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -47,7 +47,7 @@ def get_tool(self, name: str) -> Tool | None: def list_tools(self, prefix: str | None = None) -> list[Tool]: """List all registered tools, optionally filtered by URI prefix.""" tools = list(self._tools.values()) - tools = filter_by_prefix(tools, prefix, lambda t: str(t.uri)) + tools = filter_by_prefix(tools, prefix, lambda t: t.uri) logger.debug("Listing tools", extra={"count": len(tools), "prefix": prefix}) return tools diff --git a/src/mcp/server/fastmcp/uri_utils.py b/src/mcp/server/fastmcp/uri_utils.py index 01dfe846b..8405cbf84 100644 --- a/src/mcp/server/fastmcp/uri_utils.py +++ b/src/mcp/server/fastmcp/uri_utils.py @@ -3,6 +3,8 @@ from collections.abc import Callable from typing import TypeVar +from pydantic import AnyUrl + from mcp.types import PROMPT_SCHEME, TOOL_SCHEME T = TypeVar("T") @@ -33,7 +35,7 @@ def normalize_to_prompt_uri(name_or_uri: str) -> str: return normalize_to_uri(name_or_uri, PROMPT_SCHEME) -def filter_by_prefix(items: list[T], prefix: str | None, uri_getter: Callable[[T], str]) -> list[T]: +def filter_by_prefix(items: list[T], prefix: str | None, uri_getter: Callable[[T], AnyUrl | str]) -> list[T]: """Filter items by URI prefix. Args: @@ -50,7 +52,7 @@ def filter_by_prefix(items: list[T], prefix: str | None, uri_getter: Callable[[T # Filter items where the URI starts with the prefix filtered: list[T] = [] for item in items: - uri = uri_getter(item) + uri = str(uri_getter(item)) if uri.startswith(prefix): # If prefix ends with a separator, we already have a proper boundary if prefix.endswith(("/", "?", "#")): diff --git a/src/mcp/types.py b/src/mcp/types.py index 7bee55de4..59c9a5f45 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -6,8 +6,9 @@ from typing_extensions import deprecated # URI scheme constants -TOOL_SCHEME = "tool:/" -PROMPT_SCHEME = "prompt:/" +MCP_SCHEME = "mcp" +TOOL_SCHEME = f"{MCP_SCHEME}://tools" +PROMPT_SCHEME = f"{MCP_SCHEME}://prompts" """ Model Context Protocol bindings for Python @@ -641,9 +642,7 @@ class PromptArgument(BaseModel): class Prompt(BaseMetadata): """A prompt or prompt template that the server offers.""" - uri: ( - Annotated[AnyUrl, UrlConstraints(allowed_schemes=[PROMPT_SCHEME.rstrip(":/ ")], host_required=False)] | None - ) = None + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[MCP_SCHEME], host_required=False)] | None = None """URI for the prompt. Auto-generated if not provided.""" description: str | None = None """An optional description of what this prompt provides.""" @@ -662,6 +661,15 @@ def __init__(self, **data: Any) -> None: data["uri"] = AnyUrl(f"{PROMPT_SCHEME}/{data['name']}") super().__init__(**data) + @model_validator(mode="after") + def validate_prompt_uri(self) -> "Prompt": + """Validate that prompt URI starts with the correct prefix.""" + if self.uri is not None: + uri_str = str(self.uri) + if not uri_str.startswith(f"{PROMPT_SCHEME}/"): + raise ValueError(f"Prompt URI must start with {PROMPT_SCHEME}/") + return self + class ListPromptsResult(ListResult): """The server's response to a prompts/list request from the client.""" @@ -870,9 +878,7 @@ class ToolAnnotations(BaseModel): class Tool(BaseMetadata): """Definition for a tool the client can call.""" - uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[TOOL_SCHEME.rstrip(":/ ")], host_required=False)] | None = ( - None - ) + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[MCP_SCHEME], host_required=False)] | None = None """URI for the tool. Auto-generated if not provided.""" description: str | None = None """A human-readable description of the tool.""" @@ -898,6 +904,15 @@ def __init__(self, **data: Any) -> None: data["uri"] = AnyUrl(f"{TOOL_SCHEME}/{data['name']}") super().__init__(**data) + @model_validator(mode="after") + def validate_tool_uri(self) -> "Tool": + """Validate that tool URI starts with the correct prefix.""" + if self.uri is not None: + uri_str = str(self.uri) + if not uri_str.startswith(f"{TOOL_SCHEME}/"): + raise ValueError(f"Tool URI must start with {TOOL_SCHEME}/") + return self + class ListToolsResult(ListResult): """The server's response to a tools/list request from the client.""" diff --git a/tests/server/fastmcp/test_tool_manager.py b/tests/server/fastmcp/test_tool_manager.py index c5adeea29..c4041bc24 100644 --- a/tests/server/fastmcp/test_tool_manager.py +++ b/tests/server/fastmcp/test_tool_manager.py @@ -62,7 +62,7 @@ class AddArguments(ArgModelBase): # warn on duplicate tools with caplog.at_level(logging.WARNING): manager = ToolManager(True, tools=[original_tool, original_tool]) - assert "Tool already exists: tool://sum" in caplog.text + assert f"Tool already exists: {TOOL_SCHEME}/sum" in caplog.text @pytest.mark.anyio async def test_async_function(self): @@ -163,7 +163,7 @@ def f(x: int) -> int: manager.add_tool(f) with caplog.at_level(logging.WARNING): manager.add_tool(f) - assert "Tool already exists: tool://f" in caplog.text + assert f"Tool already exists: {TOOL_SCHEME}/f" in caplog.text def test_disable_warn_on_duplicate_tools(self, caplog): """Test disabling warning on duplicate tools.""" @@ -351,7 +351,7 @@ def math_multiply(a: int, b: int) -> int: multiply_tool.uri = f"{TOOL_SCHEME}/custom/math/multiply" manager._tools[str(multiply_tool.uri)] = multiply_tool - # Call by default URI (tool://function_name) + # Call by default URI (TOOL_SCHEME/function_name) result = await manager.call_tool(f"{TOOL_SCHEME}/math_add", {"a": 5, "b": 3}) assert result == 8 diff --git a/tests/test_types.py b/tests/test_types.py index 9df98f8e6..8370b10e7 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -58,7 +58,7 @@ def test_resource_uri(): assert resource.name == "test" assert str(resource.uri) == "file://test.txt/" # AnyUrl adds trailing slash - # Should reject tool:// and prompt:// schemes + # Should reject TOOL_SCHEME and PROMPT_SCHEME schemes with pytest.raises(ValueError, match="reserved schemes"): Resource(name="test", uri=AnyUrl(f"{TOOL_SCHEME}/test")) @@ -68,7 +68,7 @@ def test_resource_uri(): def test_tool_uri_validation(): """Test that Tool requires URI with tool scheme.""" - # Tool requires URI with tool:// scheme + # Tool requires URI with TOOL_SCHEME tool = Tool(name="calculator", inputSchema={"type": "object"}, uri=f"{TOOL_SCHEME}/calculator") assert tool.name == "calculator" assert str(tool.uri) == f"{TOOL_SCHEME}/calculator" @@ -80,7 +80,7 @@ def test_tool_uri_validation(): def test_prompt_uri_validation(): """Test that Prompt requires URI with prompt scheme.""" - # Prompt requires URI with prompt:// scheme + # Prompt requires URI with PROMPT_SCHEME prompt = Prompt(name="greeting", uri=f"{PROMPT_SCHEME}/greeting") assert prompt.name == "greeting" assert str(prompt.uri) == f"{PROMPT_SCHEME}/greeting" From 5a752ad34d8c29f375ddc02cec1b8341d5718641 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sat, 2 Aug 2025 18:18:47 -0700 Subject: [PATCH 11/15] refactor: Make URI fields required and block all MCP scheme usage in resources - Changed Tool and Prompt URI fields from optional to required (auto-generated) - Updated Resource validator to block any URI using the MCP scheme (mcp://) - Removed unnecessary None checks in URI validators since fields are now required - Updated tests to match new error message This provides stronger type safety and clearer API contracts while maintaining backward compatibility through auto-generation. --- src/mcp/types.py | 26 +++++++++++--------------- tests/test_types.py | 6 +++--- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/mcp/types.py b/src/mcp/types.py index 59c9a5f45..bfbc76df9 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -440,12 +440,10 @@ class Resource(BaseMetadata): @model_validator(mode="after") def validate_uri_scheme(self) -> "Resource": - """Ensure resource URI doesn't use reserved schemes.""" + """Ensure resource URI doesn't use reserved MCP scheme.""" uri_str = str(self.uri) - if uri_str.startswith((TOOL_SCHEME, PROMPT_SCHEME)): - raise ValueError( - f"Resource URI cannot use reserved schemes '{TOOL_SCHEME}' or '{PROMPT_SCHEME}', got: {self.uri}" - ) + if uri_str.startswith(f"{MCP_SCHEME}://"): + raise ValueError(f"Resource URI cannot use reserved MCP scheme '{MCP_SCHEME}://', got: {self.uri}") return self @@ -642,7 +640,7 @@ class PromptArgument(BaseModel): class Prompt(BaseMetadata): """A prompt or prompt template that the server offers.""" - uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[MCP_SCHEME], host_required=False)] | None = None + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[MCP_SCHEME], host_required=False)] """URI for the prompt. Auto-generated if not provided.""" description: str | None = None """An optional description of what this prompt provides.""" @@ -664,10 +662,9 @@ def __init__(self, **data: Any) -> None: @model_validator(mode="after") def validate_prompt_uri(self) -> "Prompt": """Validate that prompt URI starts with the correct prefix.""" - if self.uri is not None: - uri_str = str(self.uri) - if not uri_str.startswith(f"{PROMPT_SCHEME}/"): - raise ValueError(f"Prompt URI must start with {PROMPT_SCHEME}/") + uri_str = str(self.uri) + if not uri_str.startswith(f"{PROMPT_SCHEME}/"): + raise ValueError(f"Prompt URI must start with {PROMPT_SCHEME}/") return self @@ -878,7 +875,7 @@ class ToolAnnotations(BaseModel): class Tool(BaseMetadata): """Definition for a tool the client can call.""" - uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[MCP_SCHEME], host_required=False)] | None = None + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[MCP_SCHEME], host_required=False)] """URI for the tool. Auto-generated if not provided.""" description: str | None = None """A human-readable description of the tool.""" @@ -907,10 +904,9 @@ def __init__(self, **data: Any) -> None: @model_validator(mode="after") def validate_tool_uri(self) -> "Tool": """Validate that tool URI starts with the correct prefix.""" - if self.uri is not None: - uri_str = str(self.uri) - if not uri_str.startswith(f"{TOOL_SCHEME}/"): - raise ValueError(f"Tool URI must start with {TOOL_SCHEME}/") + uri_str = str(self.uri) + if not uri_str.startswith(f"{TOOL_SCHEME}/"): + raise ValueError(f"Tool URI must start with {TOOL_SCHEME}/") return self diff --git a/tests/test_types.py b/tests/test_types.py index 8370b10e7..88f23aefd 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -58,11 +58,11 @@ def test_resource_uri(): assert resource.name == "test" assert str(resource.uri) == "file://test.txt/" # AnyUrl adds trailing slash - # Should reject TOOL_SCHEME and PROMPT_SCHEME schemes - with pytest.raises(ValueError, match="reserved schemes"): + # Should reject MCP scheme + with pytest.raises(ValueError, match="reserved MCP scheme"): Resource(name="test", uri=AnyUrl(f"{TOOL_SCHEME}/test")) - with pytest.raises(ValueError, match="reserved schemes"): + with pytest.raises(ValueError, match="reserved MCP scheme"): Resource(name="test", uri=AnyUrl(f"{PROMPT_SCHEME}/test")) From cf7103e6ba5884b38313e3aff2942908fc22baf0 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sun, 3 Aug 2025 00:52:14 -0700 Subject: [PATCH 12/15] nit: Remove unnecessary explicit URI parameters in tests --- tests/server/fastmcp/test_title.py | 12 +++++------- tests/server/test_lowlevel_input_validation.py | 6 +----- tests/shared/test_streamable_http.py | 6 ------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/tests/server/fastmcp/test_title.py b/tests/server/fastmcp/test_title.py index e6f3f9f5d..1dc3ccaae 100644 --- a/tests/server/fastmcp/test_title.py +++ b/tests/server/fastmcp/test_title.py @@ -7,7 +7,7 @@ from mcp.server.fastmcp.resources import FunctionResource from mcp.shared.memory import create_connected_server_and_client_session from mcp.shared.metadata_utils import get_display_name -from mcp.types import PROMPT_SCHEME, TOOL_SCHEME, Prompt, Resource, ResourceTemplate, Tool, ToolAnnotations +from mcp.types import Prompt, Resource, ResourceTemplate, Tool, ToolAnnotations @pytest.mark.anyio @@ -181,15 +181,14 @@ async def test_get_display_name_utility(): """Test the get_display_name utility function.""" # Test tool precedence: title > annotations.title > name - tool_name_only = Tool(name="test_tool", uri=f"{TOOL_SCHEME}/test_tool", inputSchema={}) + tool_name_only = Tool(name="test_tool", inputSchema={}) assert get_display_name(tool_name_only) == "test_tool" - tool_with_title = Tool(name="test_tool", uri=f"{TOOL_SCHEME}/test_tool", title="Test Tool", inputSchema={}) + tool_with_title = Tool(name="test_tool", title="Test Tool", inputSchema={}) assert get_display_name(tool_with_title) == "Test Tool" tool_with_annotations = Tool( name="test_tool", - uri=f"{TOOL_SCHEME}/test_tool", inputSchema={}, annotations=ToolAnnotations(title="Annotated Tool"), ) @@ -197,7 +196,6 @@ async def test_get_display_name_utility(): tool_with_both = Tool( name="test_tool", - uri=f"{TOOL_SCHEME}/test_tool", title="Primary Title", inputSchema={}, annotations=ToolAnnotations(title="Secondary Title"), @@ -211,10 +209,10 @@ async def test_get_display_name_utility(): resource_with_title = Resource(uri=AnyUrl("file://test"), name="test_res", title="Test Resource") assert get_display_name(resource_with_title) == "Test Resource" - prompt = Prompt(name="test_prompt", uri=f"{PROMPT_SCHEME}/test_prompt") + prompt = Prompt(name="test_prompt") assert get_display_name(prompt) == "test_prompt" - prompt_with_title = Prompt(name="test_prompt", uri=f"{PROMPT_SCHEME}/test_prompt", title="Test Prompt") + prompt_with_title = Prompt(name="test_prompt", title="Test Prompt") assert get_display_name(prompt_with_title) == "Test Prompt" template = ResourceTemplate(uriTemplate="file://{id}", name="test_template") diff --git a/tests/server/test_lowlevel_input_validation.py b/tests/server/test_lowlevel_input_validation.py index be9dc2500..4f729c5fe 100644 --- a/tests/server/test_lowlevel_input_validation.py +++ b/tests/server/test_lowlevel_input_validation.py @@ -14,7 +14,7 @@ from mcp.server.session import ServerSession from mcp.shared.message import SessionMessage from mcp.shared.session import RequestResponder -from mcp.types import TOOL_SCHEME, CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool +from mcp.types import CallToolResult, ClientResult, ServerNotification, ServerRequest, TextContent, Tool async def run_tool_test( @@ -99,7 +99,6 @@ async def handle_messages(): def create_add_tool() -> Tool: """Create a standard 'add' tool for testing.""" return Tool( - uri=f"{TOOL_SCHEME}/add", name="add", description="Add two numbers", inputSchema={ @@ -190,7 +189,6 @@ async def test_cache_refresh_on_missing_tool(): """Test that tool cache is refreshed when tool is not found.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/multiply", name="multiply", description="Multiply two numbers", inputSchema={ @@ -232,7 +230,6 @@ async def test_enum_constraint_validation(): """Test that enum constraints are validated.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/greet", name="greet", description="Greet someone", inputSchema={ @@ -270,7 +267,6 @@ async def test_tool_not_in_list_logs_warning(caplog): """Test that calling a tool not in list_tools logs a warning and skips validation.""" tools = [ Tool( - uri=f"{TOOL_SCHEME}/add", name="add", description="Add two numbers", inputSchema={ diff --git a/tests/shared/test_streamable_http.py b/tests/shared/test_streamable_http.py index 8f1f14f3f..56ecf59fe 100644 --- a/tests/shared/test_streamable_http.py +++ b/tests/shared/test_streamable_http.py @@ -45,7 +45,6 @@ ) from mcp.shared.session import RequestResponder from mcp.types import ( - TOOL_SCHEME, InitializeResult, TextContent, TextResourceContents, @@ -147,31 +146,26 @@ async def handle_list_tools(_) -> list[Tool]: inputSchema={"type": "object", "properties": {}}, ), Tool( - uri=f"{TOOL_SCHEME}/test_tool_with_standalone_notification", name="test_tool_with_standalone_notification", description="A test tool that sends a notification", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri=f"{TOOL_SCHEME}/long_running_with_checkpoints", name="long_running_with_checkpoints", description="A long-running tool that sends periodic notifications", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri=f"{TOOL_SCHEME}/test_sampling_tool", name="test_sampling_tool", description="A tool that triggers server-side sampling", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri=f"{TOOL_SCHEME}/wait_for_lock_with_notification", name="wait_for_lock_with_notification", description="A tool that sends a notification and waits for lock", inputSchema={"type": "object", "properties": {}}, ), Tool( - uri=f"{TOOL_SCHEME}/release_lock", name="release_lock", description="A tool that releases the lock", inputSchema={"type": "object", "properties": {}}, From e4614ba17f2de926e445f7d1fe6367b2b9c0d76a Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sun, 3 Aug 2025 15:37:02 -0700 Subject: [PATCH 13/15] refactor: Replace single prefix filter with multi-path URI filters --- src/mcp/.types.py.~undo-tree~ | 881 ++++++++++++++++++ src/mcp/client/session.py | 30 +- src/mcp/server/fastmcp/prompts/manager.py | 10 +- .../server/fastmcp/prompts/prompt_manager.py | 10 +- .../fastmcp/resources/resource_manager.py | 32 +- src/mcp/server/fastmcp/server.py | 40 +- src/mcp/server/fastmcp/tools/tool_manager.py | 10 +- src/mcp/server/fastmcp/uri_utils.py | 31 +- src/mcp/types.py | 11 +- tests/server/fastmcp/prompts/test_manager.py | 23 +- .../resources/test_resource_manager.py | 30 +- tests/server/fastmcp/test_tool_manager.py | 21 +- tests/server/fastmcp/test_uri_utils.py | 123 +-- types_protocol_changes.md | 67 ++ 14 files changed, 1164 insertions(+), 155 deletions(-) create mode 100644 src/mcp/.types.py.~undo-tree~ create mode 100644 types_protocol_changes.md diff --git a/src/mcp/.types.py.~undo-tree~ b/src/mcp/.types.py.~undo-tree~ new file mode 100644 index 000000000..9e447dcb4 --- /dev/null +++ b/src/mcp/.types.py.~undo-tree~ @@ -0,0 +1,881 @@ +(undo-tree-save-format-version . 1) +"7c2534cb5695c3932bb3680b0e4064ac87d139ad" +[nil nil nil nil (26766 23935 767928 0) 0 nil] +([nil current ((132 . 30686) (#("BaseModel, ConfigDict, Field, FileUrl, RootModel, model_validator +from pydantic.networks import AnyUrl, UrlConstraints +from typing_extensions import deprecated + +\"\"\" +Model Context Protocol bindings for Python + +These bindings were generated from https://github.com/modelcontextprotocol/specification, +using Claude, with a prompt something like the following: + +Generate idiomatic Python bindings for this schema for MCP, or the \"Model Context +Protocol.\" The schema is defined in TypeScript, but there's also a JSON Schema version +for reference. + +* For the bindings, let's use Pydantic V2 models. +* Each model should allow extra fields everywhere, by specifying `model_config = + ConfigDict(extra='allow')`. Do this in every case, instead of a custom base class. +* Union types should be represented with a Pydantic `RootModel`. +* Define additional model classes instead of using dictionaries. Do this even if they're + not separate types in the schema. +\"\"\" + +LATEST_PROTOCOL_VERSION = \"2025-06-18\" + +\"\"\" +The default negotiated version of the Model Context Protocol when no version is specified. +We need this to satisfy the MCP specification, which requires the server to assume a +specific version if none is provided by the client. See section \"Protocol Version Header\" at +https://modelcontextprotocol.io/specification +\"\"\" +DEFAULT_NEGOTIATED_VERSION = \"2025-03-26\" + +ProgressToken = str | int +Cursor = str +Role = Literal[\"user\", \"assistant\"] +RequestId = Annotated[int, Field(strict=True)] | str +AnyFunction: TypeAlias = Callable[..., Any] + + +class RequestParams(BaseModel): + class Meta(BaseModel): + progressToken: ProgressToken | None = None + \"\"\" + If specified, the caller requests out-of-band progress notifications for + this request (as represented by notifications/progress). The value of this + parameter is an opaque token that will be attached to any subsequent + notifications. The receiver is not obligated to provide these notifications. + \"\"\" + + model_config = ConfigDict(extra=\"allow\") + + meta: Meta | None = Field(alias=\"_meta\", default=None) + + +class ListRequestParams(RequestParams): + prefix: str | None = None + \"\"\"Optional prefix to filter results by URI.\"\"\" + + cursor: Cursor | None = None + \"\"\" + An opaque token representing the current pagination position. + If provided, the server should return results starting after this cursor. + \"\"\" + + +class NotificationParams(BaseModel): + class Meta(BaseModel): + model_config = ConfigDict(extra=\"allow\") + + meta: Meta | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + + +RequestParamsT = TypeVar(\"RequestParamsT\", bound=RequestParams | dict[str, Any] | None) +NotificationParamsT = TypeVar(\"NotificationParamsT\", bound=NotificationParams | dict[str, Any] | None) +MethodT = TypeVar(\"MethodT\", bound=str) + + +class Request(BaseModel, Generic[RequestParamsT, MethodT]): + \"\"\"Base class for JSON-RPC requests.\"\"\" + + method: MethodT + params: RequestParamsT + model_config = ConfigDict(extra=\"allow\") + + +class ListRequest(Request[ListRequestParams | None, MethodT], Generic[MethodT]): + \"\"\"Base class for list requests, + matching the schema's ListRequest interface.\"\"\" + + params: ListRequestParams | None = None + + +class Notification(BaseModel, Generic[NotificationParamsT, MethodT]): + \"\"\"Base class for JSON-RPC notifications.\"\"\" + + method: MethodT + params: NotificationParamsT + model_config = ConfigDict(extra=\"allow\") + + +class Result(BaseModel): + \"\"\"Base class for JSON-RPC results.\"\"\" + + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ListResult(Result): + nextCursor: Cursor | None = None + \"\"\" + An opaque token representing the pagination position after the last returned result. + If present, there may be more results available. + \"\"\" + + +class JSONRPCRequest(Request[dict[str, Any] | None, str]): + \"\"\"A request that expects a response.\"\"\" + + jsonrpc: Literal[\"2.0\"] + id: RequestId + method: str + params: dict[str, Any] | None = None + + +class JSONRPCNotification(Notification[dict[str, Any] | None, str]): + \"\"\"A notification which does not expect a response.\"\"\" + + jsonrpc: Literal[\"2.0\"] + params: dict[str, Any] | None = None + + +class JSONRPCResponse(BaseModel): + \"\"\"A successful (non-error) response to a request.\"\"\" + + jsonrpc: Literal[\"2.0\"] + id: RequestId + result: dict[str, Any] + model_config = ConfigDict(extra=\"allow\") + + +# SDK error codes +CONNECTION_CLOSED = -32000 +# REQUEST_TIMEOUT = -32001 # the typescript sdk uses this + +# Standard JSON-RPC error codes +PARSE_ERROR = -32700 +INVALID_REQUEST = -32600 +METHOD_NOT_FOUND = -32601 +INVALID_PARAMS = -32602 +INTERNAL_ERROR = -32603 + + +class ErrorData(BaseModel): + \"\"\"Error information for JSON-RPC error responses.\"\"\" + + code: int + \"\"\"The error type that occurred.\"\"\" + + message: str + \"\"\" + A short description of the error. The message SHOULD be limited to a concise single + sentence. + \"\"\" + + data: Any | None = None + \"\"\" + Additional information about the error. The value of this member is defined by the + sender (e.g. detailed error information, nested errors etc.). + \"\"\" + + model_config = ConfigDict(extra=\"allow\") + + +class JSONRPCError(BaseModel): + \"\"\"A response to a request that indicates an error occurred.\"\"\" + + jsonrpc: Literal[\"2.0\"] + id: str | int + error: ErrorData + model_config = ConfigDict(extra=\"allow\") + + +class JSONRPCMessage(RootModel[JSONRPCRequest | JSONRPCNotification | JSONRPCResponse | JSONRPCError]): + pass + + +class EmptyResult(Result): + \"\"\"A response that indicates success but carries no data.\"\"\" + + +class BaseMetadata(BaseModel): + \"\"\"Base class for entities with name and optional title fields.\"\"\" + + name: str + \"\"\"The programmatic name of the entity.\"\"\" + + title: str | None = None + \"\"\" + Intended for UI and end-user contexts — optimized to be human-readable and easily understood, + even by those unfamiliar with domain-specific terminology. + + If not provided, the name should be used for display (except for Tool, + where `annotations.title` should be given precedence over using `name`, + if present). + \"\"\" + + +class Implementation(BaseMetadata): + \"\"\"Describes the name and version of an MCP implementation.\"\"\" + + version: str + model_config = ConfigDict(extra=\"allow\") + + +class RootsCapability(BaseModel): + \"\"\"Capability for root operations.\"\"\" + + listChanged: bool | None = None + \"\"\"Whether the client supports notifications for changes to the roots list.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class SamplingCapability(BaseModel): + \"\"\"Capability for sampling operations.\"\"\" + + model_config = ConfigDict(extra=\"allow\") + + +class ElicitationCapability(BaseModel): + \"\"\"Capability for elicitation operations.\"\"\" + + model_config = ConfigDict(extra=\"allow\") + + +class ClientCapabilities(BaseModel): + \"\"\"Capabilities a client may support.\"\"\" + + experimental: dict[str, dict[str, Any]] | None = None + \"\"\"Experimental, non-standard capabilities that the client supports.\"\"\" + sampling: SamplingCapability | None = None + \"\"\"Present if the client supports sampling from an LLM.\"\"\" + elicitation: ElicitationCapability | None = None + \"\"\"Present if the client supports elicitation from the user.\"\"\" + roots: RootsCapability | None = None + \"\"\"Present if the client supports listing roots.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class PromptsCapability(BaseModel): + \"\"\"Capability for prompts operations.\"\"\" + + listChanged: bool | None = None + \"\"\"Whether this server supports notifications for changes to the prompt list.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ResourcesCapability(BaseModel): + \"\"\"Capability for resources operations.\"\"\" + + subscribe: bool | None = None + \"\"\"Whether this server supports subscribing to resource updates.\"\"\" + listChanged: bool | None = None + \"\"\"Whether this server supports notifications for changes to the resource list.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ToolsCapability(BaseModel): + \"\"\"Capability for tools operations.\"\"\" + + listChanged: bool | None = None + \"\"\"Whether this server supports notifications for changes to the tool list.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class LoggingCapability(BaseModel): + \"\"\"Capability for logging operations.\"\"\" + + model_config = ConfigDict(extra=\"allow\") + + +class CompletionsCapability(BaseModel): + \"\"\"Capability for completions operations.\"\"\" + + model_config = ConfigDict(extra=\"allow\") + + +class ServerCapabilities(BaseModel): + \"\"\"Capabilities that a server may support.\"\"\" + + experimental: dict[str, dict[str, Any]] | None = None + \"\"\"Experimental, non-standard capabilities that the server supports.\"\"\" + logging: LoggingCapability | None = None + \"\"\"Present if the server supports sending log messages to the client.\"\"\" + prompts: PromptsCapability | None = None + \"\"\"Present if the server offers any prompt templates.\"\"\" + resources: ResourcesCapability | None = None + \"\"\"Present if the server offers any resources to read.\"\"\" + tools: ToolsCapability | None = None + \"\"\"Present if the server offers any tools to call.\"\"\" + completions: CompletionsCapability | None = None + \"\"\"Present if the server offers autocompletion suggestions for prompts and resources.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class InitializeRequestParams(RequestParams): + \"\"\"Parameters for the initialize request.\"\"\" + + protocolVersion: str | int + \"\"\"The latest version of the Model Context Protocol that the client supports.\"\"\" + capabilities: ClientCapabilities + clientInfo: Implementation + model_config = ConfigDict(extra=\"allow\") + + +class InitializeRequest(Request[InitializeRequestParams, Literal[\"initialize\"]]): + \"\"\" + This request is sent from the client to the server when it first connects, asking it + to begin initialization. + \"\"\" + + method: Literal[\"initialize\"] + params: InitializeRequestParams + + +class InitializeResult(Result): + \"\"\"After receiving an initialize request from the client, the server sends this.\"\"\" + + protocolVersion: str | int + \"\"\"The version of the Model Context Protocol that the server wants to use.\"\"\" + capabilities: ServerCapabilities + serverInfo: Implementation + instructions: str | None = None + \"\"\"Instructions describing how to use the server and its features.\"\"\" + + +class InitializedNotification(Notification[NotificationParams | None, Literal[\"notifications/initialized\"]]): + \"\"\" + This notification is sent from the client to the server after initialization has + finished. + \"\"\" + + method: Literal[\"notifications/initialized\"] + params: NotificationParams | None = None + + +class PingRequest(Request[RequestParams | None, Literal[\"ping\"]]): + \"\"\" + A ping, issued by either the server or the client, to check that the other party is + still alive. + \"\"\" + + method: Literal[\"ping\"] + params: RequestParams | None = None + + +class ProgressNotificationParams(NotificationParams): + \"\"\"Parameters for progress notifications.\"\"\" + + progressToken: ProgressToken + \"\"\" + The progress token which was given in the initial request, used to associate this + notification with the request that is proceeding. + \"\"\" + progress: float + \"\"\" + The progress thus far. This should increase every time progress is made, even if the + total is unknown. + \"\"\" + total: float | None = None + \"\"\"Total number of items to process (or total progress required), if known.\"\"\" + message: str | None = None + \"\"\" + Message related to progress. This should provide relevant human readable + progress information. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ProgressNotification(Notification[ProgressNotificationParams, Literal[\"notifications/progress\"]]): + \"\"\" + An out-of-band notification used to inform the receiver of a progress update for a + long-running request. + \"\"\" + + method: Literal[\"notifications/progress\"] + params: ProgressNotificationParams + + +class ListResourcesRequest(ListRequest[Literal[\"resources/list\"]]): + \"\"\"Sent from the client to request a list of resources the server has.\"\"\" + + method: Literal[\"resources/list\"] + + +class Annotations(BaseModel): + audience: list[Role] | None = None + priority: Annotated[float, Field(ge=0.0, le=1.0)] | None = None + model_config = ConfigDict(extra=\"allow\") + + +class Resource(BaseMetadata): + \"\"\"A known resource that the server is capable of reading.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] + \"\"\"The URI of this resource.\"\"\" + description: str | None = None + \"\"\"A description of what this resource represents.\"\"\" + mimeType: str | None = None + \"\"\"The MIME type of this resource, if known.\"\"\" + size: int | None = None + \"\"\" + The size of the raw resource content, in bytes (i.e., before base64 encoding + or any tokenization), if known. + + This can be used by Hosts to display file sizes and estimate context window usage. + \"\"\" + annotations: Annotations | None = None + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + @model_validator(mode=\"after\") + def validate_uri_scheme(self) -> \"Resource\": + \"\"\"Ensure resource URI doesn't use reserved schemes.\"\"\" + uri_str = str(self.uri) + if uri_str.startswith((\"tool://\", \"prompt://\")): + raise ValueError(f\"Resource URI cannot use reserved schemes 'tool://' or 'prompt://', got: {self.uri}\") + return self + + +class ResourceTemplate(BaseMetadata): + \"\"\"A template description for resources available on the server.\"\"\" + + uriTemplate: str + \"\"\" + A URI template (according to RFC 6570) that can be used to construct resource + URIs. + \"\"\" + description: str | None = None + \"\"\"A human-readable description of what this template is for.\"\"\" + mimeType: str | None = None + \"\"\" + The MIME type for all resources that match this template. This should only be + included if all resources matching this template have the same type. + \"\"\" + annotations: Annotations | None = None + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ListResourcesResult(ListResult): + \"\"\"The server's response to a resources/list request from the client.\"\"\" + + resources: list[Resource] + + +class ListResourceTemplatesRequest(ListRequest[Literal[\"resources/templates/list\"]]): + \"\"\"Sent from the client to request a list of resource templates the server has.\"\"\" + + method: Literal[\"resources/templates/list\"] + + +class ListResourceTemplatesResult(ListResult): + \"\"\"The server's response to a resources/templates/list request from the client.\"\"\" + + resourceTemplates: list[ResourceTemplate] + + +class ReadResourceRequestParams(RequestParams): + \"\"\"Parameters for reading a resource.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] + \"\"\" + The URI of the resource to read. The URI can use any protocol; it is up to the + server how to interpret it. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ReadResourceRequest(Request[ReadResourceRequestParams, Literal[\"resources/read\"]]): + \"\"\"Sent from the client to the server, to read a specific resource URI.\"\"\" + + method: Literal[\"resources/read\"] + params: ReadResourceRequestParams + + +class ResourceContents(BaseModel): + \"\"\"The contents of a specific resource or sub-resource.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] + \"\"\"The URI of this resource.\"\"\" + mimeType: str | None = None + \"\"\"The MIME type of this resource, if known.\"\"\" + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class TextResourceContents(ResourceContents): + \"\"\"Text contents of a resource.\"\"\" + + text: str + \"\"\" + The text of the item. This must only be set if the item can actually be represented + as text (not binary data). + \"\"\" + + +class BlobResourceContents(ResourceContents): + \"\"\"Binary contents of a resource.\"\"\" + + blob: str + \"\"\"A base64-encoded string representing the binary data of the item.\"\"\" + + +class ReadResourceResult(Result): + \"\"\"The server's response to a resources/read request from the client.\"\"\" + + contents: list[TextResourceContents | BlobResourceContents] + + +class ResourceListChangedNotification( + Notification[NotificationParams | None, Literal[\"notifications/resources/list_changed\"]] +): + \"\"\" + An optional notification from the server to the client, informing it that the list + of resources it can read from has changed. + \"\"\" + + method: Literal[\"notifications/resources/list_changed\"] + params: NotificationParams | None = None + + +class SubscribeRequestParams(RequestParams): + \"\"\"Parameters for subscribing to a resource.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] + \"\"\" + The URI of the resource to subscribe to. The URI can use any protocol; it is up to + the server how to interpret it. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class SubscribeRequest(Request[SubscribeRequestParams, Literal[\"resources/subscribe\"]]): + \"\"\" + Sent from the client to request resources/updated notifications from the server + whenever a particular resource changes. + \"\"\" + + method: Literal[\"resources/subscribe\"] + params: SubscribeRequestParams + + +class UnsubscribeRequestParams(RequestParams): + \"\"\"Parameters for unsubscribing from a resource.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] + \"\"\"The URI of the resource to unsubscribe from.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class UnsubscribeRequest(Request[UnsubscribeRequestParams, Literal[\"resources/unsubscribe\"]]): + \"\"\" + Sent from the client to request cancellation of resources/updated notifications from + the server. + \"\"\" + + method: Literal[\"resources/unsubscribe\"] + params: UnsubscribeRequestParams + + +class ResourceUpdatedNotificationParams(NotificationParams): + \"\"\"Parameters for resource update notifications.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] + \"\"\" + The URI of the resource that has been updated. This might be a sub-resource of the + one that the client actually subscribed to. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ResourceUpdatedNotification( + Notification[ResourceUpdatedNotificationParams, Literal[\"notifications/resources/updated\"]] +): + \"\"\" + A notification from the server to the client, informing it that a resource has + changed and may need to be read again. + \"\"\" + + method: Literal[\"notifications/resources/updated\"] + params: ResourceUpdatedNotificationParams + + +class ListPromptsRequest(ListRequest[Literal[\"prompts/list\"]]): + \"\"\"Sent from the client to request a list of prompts and prompt templates.\"\"\" + + method: Literal[\"prompts/list\"] + + +class PromptArgument(BaseModel): + \"\"\"An argument for a prompt template.\"\"\" + + name: str + \"\"\"The name of the argument.\"\"\" + description: str | None = None + \"\"\"A human-readable description of the argument.\"\"\" + required: bool | None = None + \"\"\"Whether this argument must be provided.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class Prompt(BaseMetadata): + \"\"\"A prompt or prompt template that the server offers.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[\"prompt\"], host_required=False)] + \"\"\"URI for the prompt. Must use 'prompt' scheme.\"\"\" + description: str | None = None + \"\"\"An optional description of what this prompt provides.\"\"\" + arguments: list[PromptArgument] | None = None + \"\"\"A list of arguments to use for templating the prompt.\"\"\" + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ListPromptsResult(ListResult): + \"\"\"The server's response to a prompts/list request from the client.\"\"\" + + prompts: list[Prompt] + + +class GetPromptRequestParams(RequestParams): + \"\"\"Parameters for getting a prompt.\"\"\" + + name: str + \"\"\"The name of the prompt or prompt template.\"\"\" + arguments: dict[str, str] | None = None + \"\"\"Arguments to use for templating the prompt.\"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class GetPromptRequest(Request[GetPromptRequestParams, Literal[\"prompts/get\"]]): + \"\"\"Used by the client to get a prompt provided by the server.\"\"\" + + method: Literal[\"prompts/get\"] + params: GetPromptRequestParams + + +class TextContent(BaseModel): + \"\"\"Text content for a message.\"\"\" + + type: Literal[\"text\"] + text: str + \"\"\"The text content of the message.\"\"\" + annotations: Annotations | None = None + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ImageContent(BaseModel): + \"\"\"Image content for a message.\"\"\" + + type: Literal[\"image\"] + data: str + \"\"\"The base64-encoded image data.\"\"\" + mimeType: str + \"\"\" + The MIME type of the image. Different providers may support different + image types. + \"\"\" + annotations: Annotations | None = None + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class AudioContent(BaseModel): + \"\"\"Audio content for a message.\"\"\" + + type: Literal[\"audio\"] + data: str + \"\"\"The base64-encoded audio data.\"\"\" + mimeType: str + \"\"\" + The MIME type of the audio. Different providers may support different + audio types. + \"\"\" + annotations: Annotations | None = None + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class SamplingMessage(BaseModel): + \"\"\"Describes a message issued to or received from an LLM API.\"\"\" + + role: Role + content: TextContent | ImageContent | AudioContent + model_config = ConfigDict(extra=\"allow\") + + +class EmbeddedResource(BaseModel): + \"\"\" + The contents of a resource, embedded into a prompt or tool call result. + + It is up to the client how best to render embedded resources for the benefit + of the LLM and/or the user. + \"\"\" + + type: Literal[\"resource\"] + resource: TextResourceContents | BlobResourceContents + annotations: Annotations | None = None + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class ResourceLink(Resource): + \"\"\" + A resource that the server is capable of reading, included in a prompt or tool call result. + + Note: resource links returned by tools are not guaranteed to appear in the results of `resources/list` requests. + \"\"\" + + type: Literal[\"resource_link\"] + + +ContentBlock = TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource +\"\"\"A content block that can be used in prompts and tool results.\"\"\" + +Content: TypeAlias = ContentBlock +# \"\"\"DEPRECATED: Content is deprecated, you should use ContentBlock directly.\"\"\" + + +class PromptMessage(BaseModel): + \"\"\"Describes a message returned as part of a prompt.\"\"\" + + role: Role + content: ContentBlock + model_config = ConfigDict(extra=\"allow\") + + +class GetPromptResult(Result): + \"\"\"The server's response to a prompts/get request from the client.\"\"\" + + description: str | None = None + \"\"\"An optional description for the prompt.\"\"\" + messages: list[PromptMessage] + + +class PromptListChangedNotification( + Notification[NotificationParams | None, Literal[\"notifications/prompts/list_changed\"]] +): + \"\"\" + An optional notification from the server to the client, informing it that the list + of prompts it offers has changed. + \"\"\" + + method: Literal[\"notifications/prompts/list_changed\"] + params: NotificationParams | None = None + + +class ListToolsRequest(ListRequest[Literal[\"tools/list\"]]): + \"\"\"Sent from the client to request a list of tools the server has.\"\"\" + + method: Literal[\"tools/list\"] + + +class ToolAnnotations(BaseModel): + \"\"\" + Additional properties describing a Tool to clients. + + NOTE: all properties in ToolAnnotations are **hints**. + They are not guaranteed to provide a faithful description of + tool behavior (including descriptive properties like `title`). + + Clients should never make tool use decisions based on ToolAnnotations + received from untrusted servers. + \"\"\" + + title: str | None = None + \"\"\"A human-readable title for the tool.\"\"\" + + readOnlyHint: bool | None = None + \"\"\" + If true, the tool does not modify its environment. + Default: false + \"\"\" + + destructiveHint: bool | None = None + \"\"\" + If true, the tool may perform destructive updates to its environment. + If false, the tool performs only additive updates. + (This property is meaningful only when `readOnlyHint == false`) + Default: true + \"\"\" + + idempotentHint: bool | None = None + \"\"\" + If true, calling the tool repeatedly with the same arguments + will have no additional effect on the its environment. + (This property is meaningful only when `readOnlyHint == false`) + Default: false + \"\"\" + + openWorldHint: bool | None = None + \"\"\" + If true, this tool may interact with an \"open world\" of external + entities. If false, the tool's domain of interaction is closed. + For example, the world of a web search tool is open, whereas that + of a memory tool is not. + Default: true + \"\"\" + model_config = ConfigDict(extra=\"allow\") + + +class Tool(BaseMetadata): + \"\"\"Definition for a tool the client can call.\"\"\" + + uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[\"tool\"], host_required=False)] + \"\"\"URI for the tool. Must use 'tool' scheme.\"\"\" + description: str | None = None + \"\"\"A human-readable description of the tool.\"\"\" + inputSchema: dict[str, Any] + \"\"\"A JSON Schema object defining the expected parameters for the tool.\"\"\" + outputSchema: dict[str, Any] | None = None + \"\"\" + An optional JSON Schema object defining the structure of the tool's output + returned in the structuredContent field of a CallToolResult. + \"\"\" + annotations: ToolAnnotations | None = None + \"\"\"Optional additional tool information.\"\"\" + meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) + \"\"\" + See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) + for notes on _meta usage. + \"\"\" + model_config = ConfigDict(extra=\"allow\")" 0 66 (fontified t) 66 70 (face font-lock-keyword-face fontified t) 70 89 (fontified t) 89 95 (face font-lock-keyword-face fontified t) 95 119 (fontified t) 119 123 (face font-lock-keyword-face fontified t) 123 142 (fontified t) 142 148 (face font-lock-keyword-face fontified t) 148 161 (fontified t) 161 163 (face font-lock-string-face fontified t) 163 164 (face font-lock-string-face fontified t syntax-table (15)) 164 949 (face font-lock-string-face fontified t) 949 950 (face font-lock-string-face fontified t syntax-table (15)) 950 952 (face font-lock-string-face fontified t) 952 954 (fontified t) 954 977 (face font-lock-variable-name-face fontified t) 977 978 (fontified t) 978 979 (face font-lock-operator-face fontified t) 979 980 (fontified t) 980 992 (face font-lock-string-face fontified t) 992 994 (fontified t) 994 996 (face font-lock-doc-face fontified t) 996 997 (face font-lock-doc-face fontified t syntax-table (15)) 997 1313 (face font-lock-doc-face fontified t) 1313 1314 (face font-lock-doc-face fontified t syntax-table (15)) 1314 1316 (face font-lock-doc-face fontified t) 1316 1317 (fontified t) 1317 1343 (face font-lock-variable-name-face fontified t) 1343 1344 (fontified t) 1344 1345 (face font-lock-operator-face fontified t) 1345 1346 (fontified t) 1346 1358 (face font-lock-string-face fontified t) 1358 1360 (fontified t) 1360 1369 (face font-lock-variable-name-face fontified t) 1369 1373 (face font-lock-variable-name-face fontified t) 1373 1374 (fontified t) 1374 1375 (face font-lock-operator-face fontified t) 1375 1376 (fontified t) 1376 1379 (face font-lock-builtin-face fontified t) 1379 1380 (fontified t) 1380 1381 (face font-lock-operator-face fontified t) 1381 1382 (fontified t) 1382 1385 (face font-lock-builtin-face fontified t) 1385 1386 (fontified t) 1386 1392 (face font-lock-variable-name-face fontified t) 1392 1393 (fontified t) 1393 1394 (face font-lock-operator-face fontified t) 1394 1395 (fontified t) 1395 1398 (face font-lock-builtin-face fontified t) 1398 1399 (fontified t) 1399 1403 (face font-lock-variable-name-face fontified t) 1403 1404 (fontified t) 1404 1405 (face font-lock-operator-face fontified t) 1405 1413 (fontified t) 1413 1414 (face (rainbow-delimiters-depth-1-face) fontified t) 1414 1420 (face font-lock-string-face fontified t) 1420 1422 (fontified t) 1422 1433 (face font-lock-string-face fontified t) 1433 1434 (face (rainbow-delimiters-depth-1-face) fontified t) 1434 1435 (fontified t) 1435 1444 (face font-lock-variable-name-face fontified t) 1444 1445 (fontified t) 1445 1446 (face font-lock-operator-face fontified t) 1446 1456 (fontified t) 1456 1457 (face (rainbow-delimiters-depth-1-face) fontified t) 1457 1460 (face font-lock-builtin-face fontified t) 1460 1467 (fontified t) 1467 1468 (face (rainbow-delimiters-depth-2-face) fontified t) 1468 1474 (fontified t) 1474 1475 (face font-lock-operator-face fontified t) 1475 1479 (face font-lock-constant-face fontified t) 1479 1480 (face (rainbow-delimiters-depth-2-face) fontified t) 1480 1481 (face (rainbow-delimiters-depth-1-face) fontified t) 1481 1482 (fontified t) 1482 1483 (face font-lock-operator-face fontified t) 1483 1484 (fontified t) 1484 1487 (face font-lock-builtin-face fontified t) 1487 1488 (fontified t) 1488 1499 (face font-lock-variable-name-face fontified t) 1499 1500 (prettify-symbols-end 1632 prettify-symbols-start 1631 composition ((1 32 65 57708)) fontified t) 1500 1511 (fontified t) 1511 1512 (face font-lock-operator-face fontified t) 1512 1521 (fontified t) 1521 1522 (face (rainbow-delimiters-depth-1-face) fontified t) 1522 1530 (fontified t) 1530 1531 (face (rainbow-delimiters-depth-1-face) fontified t) 1531 1534 (fontified t) 1534 1539 (face font-lock-keyword-face fontified t) 1539 1540 (fontified t) 1540 1553 (face font-lock-type-face fontified t) 1553 1554 (face (rainbow-delimiters-depth-1-face) fontified t) 1554 1563 (fontified t) 1563 1564 (face (rainbow-delimiters-depth-1-face) fontified t) 1564 1565 (prettify-symbols-end 1697 prettify-symbols-start 1696 composition (0 1 [32 65 57708]) fontified t) 1565 1570 (fontified t) 1570 1575 (face font-lock-keyword-face fontified t) 1575 1576 (fontified t) 1576 1580 (face font-lock-type-face fontified t) 1580 1581 (face (rainbow-delimiters-depth-1-face) fontified t) 1581 1590 (fontified t) 1590 1591 (face (rainbow-delimiters-depth-1-face) fontified t) 1591 1592 (prettify-symbols-end 1724 prettify-symbols-start 1723 composition (0 1 [32 65 57708]) fontified t) 1592 1614 (fontified t) 1614 1615 (prettify-symbols-end 1747 prettify-symbols-start 1746 composition (0 1 [32 65 57708]) fontified t) 1615 1630 (fontified t) 1630 1631 (face font-lock-operator-face fontified t) 1631 1632 (fontified t) 1632 1636 (face font-lock-constant-face fontified t) 1636 1637 (fontified t) 1637 1638 (face font-lock-operator-face fontified t) 1638 1639 (fontified t) 1639 1643 (face font-lock-constant-face fontified t) 1643 1652 (fontified t) 1652 1654 (face font-lock-doc-face fontified t) 1654 1655 (face font-lock-doc-face fontified t syntax-table (15)) 1655 1990 (face font-lock-doc-face fontified t) 1990 1991 (face font-lock-doc-face fontified t syntax-table (15)) 1991 1993 (face font-lock-doc-face fontified t) 1993 2003 (fontified t) 2003 2015 (face font-lock-variable-name-face fontified t) 2015 2016 (fontified t) 2016 2017 (face font-lock-operator-face fontified t) 2017 2028 (fontified t) 2028 2029 (face (rainbow-delimiters-depth-1-face) fontified t) 2029 2034 (fontified t) 2034 2035 (face font-lock-operator-face fontified t) 2035 2042 (face font-lock-string-face fontified t) 2042 2043 (face (rainbow-delimiters-depth-1-face) fontified t) 2043 2053 (fontified t) 2053 2054 (prettify-symbols-end 2186 prettify-symbols-start 2185 composition (0 1 [32 65 57708]) fontified t) 2054 2060 (fontified t) 2060 2061 (face font-lock-operator-face fontified t) 2061 2062 (fontified t) 2062 2066 (face font-lock-constant-face fontified t) 2066 2067 (fontified t) 2067 2068 (face font-lock-operator-face fontified t) 2068 2074 (fontified t) 2074 2075 (face (rainbow-delimiters-depth-1-face) fontified t) 2075 2080 (fontified t) 2080 2081 (face font-lock-operator-face fontified t) 2081 2088 (face font-lock-string-face fontified t) 2088 2097 (fontified t) 2097 2098 (face font-lock-operator-face fontified t) 2098 2102 (face font-lock-constant-face fontified t) 2102 2103 (face (rainbow-delimiters-depth-1-face) fontified t) 2103 2106 (fontified t) 2106 2111 (face font-lock-keyword-face fontified t) 2111 2112 (fontified t) 2112 2129 (face font-lock-type-face fontified t) 2129 2130 (face (rainbow-delimiters-depth-1-face) fontified t) 2130 2143 (fontified t) 2143 2144 (face (rainbow-delimiters-depth-1-face) fontified t) 2144 2145 (prettify-symbols-end 2277 prettify-symbols-start 2276 composition (0 1 [32 65 57708]) fontified t) 2145 2156 (fontified t) 2156 2157 (prettify-symbols-end 2289 prettify-symbols-start 2288 composition (0 1 [32 65 57708]) fontified t) 2157 2158 (fontified t) 2158 2161 (face font-lock-builtin-face fontified t) 2161 2162 (fontified t) 2162 2163 (face font-lock-operator-face fontified t) 2163 2164 (fontified t) 2164 2168 (face font-lock-constant-face fontified t) 2168 2169 (fontified t) 2169 2170 (face font-lock-operator-face fontified t) 2170 2171 (fontified t) 2171 2175 (face font-lock-constant-face fontified t) 2175 2180 (fontified t) 2180 2182 (face font-lock-doc-face fontified t) 2182 2183 (face font-lock-doc-face fontified t syntax-table (15)) 2183 2224 (face font-lock-doc-face fontified t) 2224 2225 (face font-lock-doc-face fontified t syntax-table (15)) 2225 2227 (face font-lock-doc-face fontified t) 2227 2239 (fontified t) 2239 2240 (prettify-symbols-end 2372 prettify-symbols-start 2371 composition (0 1 [32 65 57708]) fontified t) 2240 2248 (fontified t) 2248 2249 (face font-lock-operator-face fontified t) 2249 2250 (fontified t) 2250 2254 (face font-lock-constant-face fontified t) 2254 2255 (fontified t) 2255 2256 (face font-lock-operator-face fontified t) 2256 2257 (fontified t) 2257 2261 (face font-lock-constant-face fontified t) 2261 2266 (fontified t) 2266 2268 (face font-lock-doc-face fontified t) 2268 2269 (face font-lock-doc-face fontified t syntax-table (15)) 2269 2418 (face font-lock-doc-face fontified t) 2418 2419 (face font-lock-doc-face fontified t syntax-table (15)) 2419 2421 (face font-lock-doc-face fontified t) 2421 2424 (fontified t) 2424 2429 (face font-lock-keyword-face fontified t) 2429 2430 (fontified t) 2430 2448 (face font-lock-type-face fontified t) 2448 2449 (face (rainbow-delimiters-depth-1-face) fontified t) 2449 2458 (fontified t) 2458 2459 (face (rainbow-delimiters-depth-1-face) fontified t) 2459 2460 (prettify-symbols-end 2592 prettify-symbols-start 2591 composition (0 1 [32 65 57708]) fontified t) 2460 2465 (fontified t) 2465 2470 (face font-lock-keyword-face fontified t) 2470 2471 (fontified t) 2471 2475 (face font-lock-type-face fontified t) 2475 2476 (face (rainbow-delimiters-depth-1-face) fontified t) 2476 2485 (fontified t) 2485 2486 (face (rainbow-delimiters-depth-1-face) fontified t) 2486 2487 (prettify-symbols-end 2619 prettify-symbols-start 2618 composition (0 1 [32 65 57708]) fontified t) 2487 2496 (fontified t) 2496 2508 (face font-lock-variable-name-face fontified t) 2508 2509 (fontified t) 2509 2510 (face font-lock-operator-face fontified t) 2510 2521 (fontified t) 2521 2522 (face (rainbow-delimiters-depth-1-face) fontified t) 2522 2527 (fontified t) 2527 2528 (face font-lock-operator-face fontified t) 2528 2535 (face font-lock-string-face fontified t) 2535 2536 (face (rainbow-delimiters-depth-1-face) fontified t) 2536 2546 (fontified t) 2546 2547 (prettify-symbols-end 2679 prettify-symbols-start 2678 composition (0 1 [32 65 57708]) fontified t) 2547 2553 (fontified t) 2553 2554 (face font-lock-operator-face fontified t) 2554 2555 (fontified t) 2555 2559 (face font-lock-constant-face fontified t) 2559 2560 (fontified t) 2560 2561 (face font-lock-operator-face fontified t) 2561 2567 (fontified t) 2567 2568 (face (rainbow-delimiters-depth-1-face) fontified t) 2568 2573 (fontified t) 2573 2574 (face font-lock-operator-face fontified t) 2574 2581 (face font-lock-string-face fontified t) 2581 2590 (fontified t) 2590 2591 (face font-lock-operator-face fontified t) 2591 2595 (face font-lock-constant-face fontified t) 2595 2596 (face (rainbow-delimiters-depth-1-face) fontified t) 2596 2601 (fontified t) 2601 2603 (face font-lock-doc-face fontified t) 2603 2604 (face font-lock-doc-face fontified t syntax-table (15)) 2604 2831 (face font-lock-doc-face fontified t) 2831 2832 (face font-lock-doc-face fontified t syntax-table (15)) 2832 2834 (face font-lock-doc-face fontified t) 2834 2837 (fontified t) 2837 2851 (face font-lock-variable-name-face fontified t) 2851 2852 (fontified t) 2852 2853 (face font-lock-operator-face fontified t) 2853 2861 (fontified t) 2861 2862 (face (rainbow-delimiters-depth-1-face) fontified t) 2862 2878 (face font-lock-string-face fontified t) 2878 2885 (fontified t) 2885 2886 (face font-lock-operator-face fontified t) 2886 2900 (fontified t) 2900 2901 (face font-lock-operator-face fontified t) 2901 2902 (fontified t) 2902 2906 (face font-lock-builtin-face fontified t) 2906 2907 (face (rainbow-delimiters-depth-2-face) fontified t) 2907 2910 (face font-lock-builtin-face fontified t) 2910 2915 (fontified t) 2915 2916 (face (rainbow-delimiters-depth-2-face) fontified t) 2916 2917 (fontified t) 2917 2918 (face font-lock-operator-face fontified t) 2918 2919 (fontified t) 2919 2923 (face font-lock-constant-face fontified t) 2923 2924 (face (rainbow-delimiters-depth-1-face) fontified t) 2924 2925 (fontified t) 2925 2944 (face font-lock-variable-name-face fontified t) 2944 2945 (fontified t) 2945 2946 (face font-lock-operator-face fontified t) 2946 2954 (fontified t) 2954 2955 (face (rainbow-delimiters-depth-1-face) fontified t) 2955 2976 (face font-lock-string-face fontified t) 2976 2983 (fontified t) 2983 2984 (face font-lock-operator-face fontified t) 2984 3003 (fontified t) 3003 3004 (face font-lock-operator-face fontified t) 3004 3005 (fontified t) 3005 3009 (face font-lock-builtin-face fontified t) 3009 3010 (face (rainbow-delimiters-depth-2-face) fontified t) 3010 3013 (face font-lock-builtin-face fontified t) 3013 3018 (fontified t) 3018 3019 (face (rainbow-delimiters-depth-2-face) fontified t) 3019 3020 (fontified t) 3020 3021 (face font-lock-operator-face fontified t) 3021 3022 (fontified t) 3022 3026 (face font-lock-constant-face fontified t) 3026 3027 (face (rainbow-delimiters-depth-1-face) fontified t) 3027 3028 (fontified t) 3028 3034 (face font-lock-variable-name-face fontified t) 3034 3035 (fontified t face font-lock-variable-name-face) 3035 3036 (fontified t) 3036 3037 (fontified t face font-lock-operator-face) 3037 3045 (fontified t) 3045 3046 (fontified t face (rainbow-delimiters-depth-1-face)) 3046 3055 (fontified t face font-lock-string-face) 3055 3062 (fontified t) 3062 3063 (fontified t face font-lock-operator-face) 3063 3066 (fontified t face font-lock-builtin-face) 3066 3067 (fontified t face (rainbow-delimiters-depth-1-face)) 3067 3068 (fontified t) 3068 3070 (fontified t) 3070 3075 (face font-lock-keyword-face fontified t) 3075 3076 (fontified t) 3076 3083 (face font-lock-type-face fontified t) 3083 3084 (face (rainbow-delimiters-depth-1-face) fontified t) 3084 3102 (fontified t) 3102 3103 (face (rainbow-delimiters-depth-2-face) fontified t) 3103 3126 (fontified t) 3126 3127 (face (rainbow-delimiters-depth-2-face) fontified t) 3127 3128 (face (rainbow-delimiters-depth-1-face) fontified t) 3128 3129 (prettify-symbols-end 3261 prettify-symbols-start 3260 composition (0 1 [32 65 57708]) fontified t) 3129 3134 (fontified t) 3134 3136 (face font-lock-doc-face fontified t) 3136 3137 (face font-lock-doc-face fontified t syntax-table (15)) 3137 3170 (face font-lock-doc-face fontified t) 3170 3171 (face font-lock-doc-face fontified t syntax-table (15)) 3171 3173 (face font-lock-doc-face fontified t) 3173 3185 (fontified t) 3185 3186 (prettify-symbols-end 3318 prettify-symbols-start 3317 composition (0 1 [32 65 57708]) fontified t) 3186 3205 (fontified t) 3205 3206 (prettify-symbols-end 3338 prettify-symbols-start 3337 composition (0 1 [32 65 57708]) fontified t) 3206 3226 (fontified t) 3226 3238 (face font-lock-variable-name-face fontified t) 3238 3239 (fontified t) 3239 3240 (face font-lock-operator-face fontified t) 3240 3251 (fontified t) 3251 3252 (face (rainbow-delimiters-depth-1-face) fontified t) 3252 3257 (fontified t) 3257 3258 (face font-lock-operator-face fontified t) 3258 3265 (face font-lock-string-face fontified t) 3265 3266 (face (rainbow-delimiters-depth-1-face) fontified t) 3266 3269 (fontified t) 3269 3274 (face font-lock-keyword-face fontified t) 3274 3275 (fontified t) 3275 3286 (face font-lock-type-face fontified t) 3286 3287 (face (rainbow-delimiters-depth-1-face) fontified t) 3287 3294 (fontified t) 3294 3295 (face (rainbow-delimiters-depth-2-face) fontified t) 3295 3313 (fontified t) 3313 3314 (face font-lock-operator-face fontified t) 3314 3315 (fontified t) 3315 3319 (face font-lock-constant-face fontified t) 3319 3328 (fontified t) 3328 3329 (face (rainbow-delimiters-depth-2-face) fontified t) 3329 3338 (fontified t) 3338 3339 (face (rainbow-delimiters-depth-2-face) fontified t) 3339 3346 (fontified t) 3346 3347 (face (rainbow-delimiters-depth-2-face) fontified t) 3347 3348 (face (rainbow-delimiters-depth-1-face) fontified t) 3348 3349 (prettify-symbols-end 3481 prettify-symbols-start 3480 composition (0 1 [32 65 57708]) fontified t) 3349 3354 (fontified t) 3354 3356 (face font-lock-doc-face fontified t) 3356 3357 (face font-lock-doc-face fontified t syntax-table (15)) 3357 3435 (face font-lock-doc-face fontified t) 3435 3436 (face font-lock-doc-face fontified t syntax-table (15)) 3436 3438 (face font-lock-doc-face fontified t) 3438 3450 (fontified t) 3450 3451 (prettify-symbols-end 3583 prettify-symbols-start 3582 composition (0 1 [32 65 57708]) fontified t) 3451 3470 (fontified t) 3470 3471 (face font-lock-operator-face fontified t) 3471 3472 (fontified t) 3472 3476 (face font-lock-constant-face fontified t) 3476 3477 (fontified t) 3477 3478 (face font-lock-operator-face fontified t) 3478 3479 (fontified t) 3479 3483 (face font-lock-constant-face fontified t) 3483 3486 (fontified t) 3486 3491 (face font-lock-keyword-face fontified t) 3491 3492 (fontified t) 3492 3504 (face font-lock-type-face fontified t) 3504 3505 (face (rainbow-delimiters-depth-1-face) fontified t) 3505 3523 (fontified t) 3523 3524 (face (rainbow-delimiters-depth-2-face) fontified t) 3524 3552 (fontified t) 3552 3553 (face (rainbow-delimiters-depth-2-face) fontified t) 3553 3554 (face (rainbow-delimiters-depth-1-face) fontified t) 3554 3555 (prettify-symbols-end 3687 prettify-symbols-start 3686 composition (0 1 [32 65 57708]) fontified t) 3555 3560 (fontified t) 3560 3562 (face font-lock-doc-face fontified t) 3562 3563 (face font-lock-doc-face fontified t syntax-table (15)) 3563 3601 (face font-lock-doc-face fontified t) 3601 3602 (face font-lock-doc-face fontified t syntax-table (15)) 3602 3604 (face font-lock-doc-face fontified t) 3604 3616 (fontified t) 3616 3617 (prettify-symbols-end 3749 prettify-symbols-start 3748 composition (0 1 [32 65 57708]) fontified t) 3617 3636 (fontified t) 3636 3637 (prettify-symbols-end 3769 prettify-symbols-start 3768 composition (0 1 [32 65 57708]) fontified t) 3637 3662 (fontified t) 3662 3674 (face font-lock-variable-name-face fontified t) 3674 3675 (fontified t) 3675 3676 (face font-lock-operator-face fontified t) 3676 3687 (fontified t) 3687 3688 (face (rainbow-delimiters-depth-1-face) fontified t) 3688 3693 (fontified t) 3693 3694 (face font-lock-operator-face fontified t) 3694 3701 (face font-lock-string-face fontified t) 3701 3702 (face (rainbow-delimiters-depth-1-face) fontified t) 3702 3705 (fontified t) 3705 3710 (face font-lock-keyword-face fontified t) 3710 3711 (fontified t) 3711 3717 (face font-lock-type-face fontified t) 3717 3718 (face (rainbow-delimiters-depth-1-face) fontified t) 3718 3727 (fontified t) 3727 3728 (face (rainbow-delimiters-depth-1-face) fontified t) 3728 3729 (prettify-symbols-end 3861 prettify-symbols-start 3860 composition (0 1 [32 65 57708]) fontified t) 3729 3734 (fontified t) 3734 3736 (face font-lock-doc-face fontified t) 3736 3737 (face font-lock-doc-face fontified t syntax-table (15)) 3737 3769 (face font-lock-doc-face fontified t) 3769 3770 (face font-lock-doc-face fontified t syntax-table (15)) 3770 3772 (face font-lock-doc-face fontified t) 3772 3782 (fontified t) 3782 3783 (prettify-symbols-end 3915 prettify-symbols-start 3914 composition (0 1 [32 65 57708]) fontified t) 3783 3784 (fontified t) 3784 3788 (face font-lock-builtin-face fontified t) 3788 3789 (face (rainbow-delimiters-depth-1-face) fontified t) 3789 3792 (face font-lock-builtin-face fontified t) 3792 3797 (fontified t) 3797 3798 (face (rainbow-delimiters-depth-1-face) fontified t) 3798 3799 (fontified t) 3799 3800 (face font-lock-operator-face fontified t) 3800 3801 (fontified t) 3801 3805 (face font-lock-constant-face fontified t) 3805 3806 (fontified t) 3806 3807 (face font-lock-operator-face fontified t) 3807 3813 (fontified t) 3813 3814 (face (rainbow-delimiters-depth-1-face) fontified t) 3814 3819 (fontified t) 3819 3820 (face font-lock-operator-face fontified t) 3820 3827 (face font-lock-string-face fontified t) 3827 3836 (fontified t) 3836 3837 (face font-lock-operator-face fontified t) 3837 3841 (face font-lock-constant-face fontified t) 3841 3842 (face (rainbow-delimiters-depth-1-face) fontified t) 3842 3847 (fontified t) 3847 3849 (face font-lock-doc-face fontified t) 3849 3850 (face font-lock-doc-face fontified t syntax-table (15)) 3850 4077 (face font-lock-doc-face fontified t) 4077 4078 (face font-lock-doc-face fontified t syntax-table (15)) 4078 4080 (face font-lock-doc-face fontified t) 4080 4085 (fontified t) 4085 4097 (face font-lock-variable-name-face fontified t) 4097 4098 (fontified t) 4098 4099 (face font-lock-operator-face fontified t) 4099 4110 (fontified t) 4110 4111 (face (rainbow-delimiters-depth-1-face) fontified t) 4111 4116 (fontified t) 4116 4117 (face font-lock-operator-face fontified t) 4117 4124 (face font-lock-string-face fontified t) 4124 4125 (face (rainbow-delimiters-depth-1-face) fontified t) 4125 4128 (fontified t) 4128 4133 (face font-lock-keyword-face fontified t) 4133 4134 (fontified t) 4134 4144 (face font-lock-type-face fontified t) 4144 4145 (face (rainbow-delimiters-depth-1-face) fontified t) 4145 4151 (fontified t) 4151 4152 (face (rainbow-delimiters-depth-1-face) fontified t) 4152 4153 (prettify-symbols-end 4285 prettify-symbols-start 4284 composition ((1 32 65 57708)) fontified t) 4153 4168 (fontified t) 4168 4169 (prettify-symbols-end 4301 prettify-symbols-start 4300 composition ((1 32 65 57708)) fontified t) 4169 4177 (fontified t) 4177 4178 (face font-lock-operator-face fontified t) 4178 4179 (fontified t) 4179 4183 (face font-lock-constant-face fontified t) 4183 4184 (fontified t) 4184 4185 (face font-lock-operator-face fontified t) 4185 4186 (fontified t) 4186 4190 (face font-lock-constant-face fontified t) 4190 4195 (fontified t) 4195 4197 (face font-lock-doc-face fontified t) 4197 4198 (face font-lock-doc-face fontified t syntax-table (15)) 4198 4345 (face font-lock-doc-face fontified t) 4345 4346 (face font-lock-doc-face fontified t syntax-table (15)) 4346 4348 (face font-lock-doc-face fontified t) 4348 4351 (fontified t) 4351 4356 (face font-lock-keyword-face fontified t) 4356 4357 (fontified t) 4357 4371 (face font-lock-type-face fontified t) 4371 4372 (face (rainbow-delimiters-depth-1-face) fontified t) 4372 4379 (fontified t) 4379 4380 (face (rainbow-delimiters-depth-2-face) fontified t) 4380 4384 (face font-lock-builtin-face fontified t) 4384 4385 (face (rainbow-delimiters-depth-3-face) fontified t) 4385 4388 (face font-lock-builtin-face fontified t) 4388 4393 (fontified t) 4393 4394 (face (rainbow-delimiters-depth-3-face) fontified t) 4394 4395 (fontified t) 4395 4396 (face font-lock-operator-face fontified t) 4396 4397 (fontified t) 4397 4401 (face font-lock-constant-face fontified t) 4401 4403 (fontified t) 4403 4406 (face font-lock-builtin-face fontified t) 4406 4407 (face (rainbow-delimiters-depth-2-face) fontified t) 4407 4408 (face (rainbow-delimiters-depth-1-face) fontified t) 4408 4409 (prettify-symbols-end 4541 prettify-symbols-start 4540 composition (0 1 [32 65 57708]) fontified t) 4409 4414 (fontified t) 4414 4416 (face font-lock-doc-face fontified t) 4416 4417 (face font-lock-doc-face fontified t syntax-table (15)) 4417 4425 (face font-lock-doc-face fontified t) 4425 4451 (face font-lock-doc-face fontified t) 4451 4452 (face font-lock-doc-face fontified t syntax-table (15)) 4452 4454 (face font-lock-doc-face fontified t) 4454 4455 (fontified t) 4455 4467 (fontified t) 4467 4468 (prettify-symbols-end 4600 prettify-symbols-start 4599 composition (0 1 [32 65 57708]) fontified t) 4468 4476 (fontified t) 4476 4477 (face (rainbow-delimiters-depth-1-face) fontified t) 4477 4482 (face font-lock-string-face fontified t) 4482 4483 (face (rainbow-delimiters-depth-1-face) fontified t) 4483 4488 (fontified t) 4488 4490 (face font-lock-builtin-face fontified t) 4490 4491 (prettify-symbols-end 4623 prettify-symbols-start 4622 composition (0 1 [32 65 57708]) fontified t) 4491 4512 (fontified t) 4512 4513 (prettify-symbols-end 4645 prettify-symbols-start 4644 composition (0 1 [32 65 57708]) fontified t) 4513 4514 (fontified t) 4514 4517 (face font-lock-builtin-face fontified t) 4517 4528 (fontified t) 4528 4529 (prettify-symbols-end 4661 prettify-symbols-start 4660 composition (0 1 [32 65 57708]) fontified t) 4529 4530 (fontified t) 4530 4534 (face font-lock-builtin-face fontified t) 4534 4535 (face (rainbow-delimiters-depth-1-face) fontified t) 4535 4538 (face font-lock-builtin-face fontified t) 4538 4543 (fontified t) 4543 4544 (face (rainbow-delimiters-depth-1-face) fontified t) 4544 4545 (fontified t) 4545 4546 (face font-lock-operator-face fontified t) 4546 4547 (fontified t) 4547 4551 (face font-lock-constant-face fontified t) 4551 4552 (fontified t) 4552 4553 (face font-lock-operator-face fontified t) 4553 4554 (fontified t) 4554 4558 (face font-lock-constant-face fontified t) 4558 4561 (fontified t) 4561 4566 (face font-lock-keyword-face fontified t) 4566 4567 (fontified t) 4567 4568 (face font-lock-type-face fontified t) 4568 4586 (fontified t face font-lock-type-face) 4586 4587 (fontified t face (rainbow-delimiters-depth-1-face)) 4587 4599 (fontified t) 4599 4600 (fontified t face (rainbow-delimiters-depth-2-face)) 4600 4604 (fontified t face font-lock-builtin-face) 4604 4605 (fontified t face (rainbow-delimiters-depth-3-face)) 4605 4608 (fontified t face font-lock-builtin-face) 4608 4613 (fontified t) 4613 4614 (fontified t face (rainbow-delimiters-depth-3-face)) 4614 4615 (fontified t) 4615 4616 (fontified t face font-lock-operator-face) 4616 4617 (fontified t) 4617 4621 (fontified t face font-lock-constant-face) 4621 4623 (fontified t) 4623 4626 (fontified t face font-lock-builtin-face) 4626 4627 (fontified t face (rainbow-delimiters-depth-2-face)) 4627 4628 (fontified t face (rainbow-delimiters-depth-1-face)) 4628 4629 (fontified t prettify-symbols-end 4761 prettify-symbols-start 4760 composition (0 1 [32 65 57708])) 4629 4630 (fontified t) 4630 4634 (fontified t) 4634 4636 (face font-lock-doc-face fontified t) 4636 4637 (face font-lock-doc-face fontified t syntax-table (15)) 4637 4685 (face font-lock-doc-face fontified t) 4685 4686 (face font-lock-doc-face fontified t syntax-table (15)) 4686 4688 (face font-lock-doc-face fontified t) 4688 4701 (fontified t) 4701 4702 (prettify-symbols-end 4834 prettify-symbols-start 4833 composition (0 1 [32 65 57708]) fontified t) 4702 4710 (fontified t) 4710 4711 (face (rainbow-delimiters-depth-1-face) fontified t) 4711 4716 (face font-lock-string-face fontified t) 4716 4717 (face (rainbow-delimiters-depth-1-face) fontified t) 4717 4728 (fontified t) 4728 4729 (prettify-symbols-end 4861 prettify-symbols-start 4860 composition (0 1 [32 65 57708]) fontified t) 4729 4730 (fontified t) 4730 4734 (face font-lock-builtin-face fontified t) 4734 4735 (face (rainbow-delimiters-depth-1-face) fontified t) 4735 4738 (face font-lock-builtin-face fontified t) 4738 4743 (fontified t) 4743 4744 (face (rainbow-delimiters-depth-1-face) fontified t) 4744 4745 (fontified t) 4745 4746 (face font-lock-operator-face fontified t) 4746 4747 (fontified t) 4747 4751 (face font-lock-constant-face fontified t) 4751 4752 (fontified t) 4752 4753 (face font-lock-operator-face fontified t) 4753 4754 (fontified t) 4754 4758 (face font-lock-constant-face fontified t) 4758 4761 (fontified t) 4761 4766 (face font-lock-keyword-face fontified t) 4766 4767 (fontified t) 4767 4782 (face font-lock-type-face fontified t) 4782 4783 (face (rainbow-delimiters-depth-1-face) fontified t) 4783 4792 (fontified t) 4792 4793 (face (rainbow-delimiters-depth-1-face) fontified t) 4793 4794 (prettify-symbols-end 4926 prettify-symbols-start 4925 composition (0 1 [32 65 57708]) fontified t) 4794 4799 (fontified t) 4799 4801 (face font-lock-doc-face fontified t) 4801 4802 (face font-lock-doc-face fontified t syntax-table (15)) 4802 4849 (face font-lock-doc-face fontified t) 4849 4850 (face font-lock-doc-face fontified t syntax-table (15)) 4850 4852 (face font-lock-doc-face fontified t) 4852 4865 (fontified t) 4865 4866 (prettify-symbols-end 4998 prettify-symbols-start 4997 composition (0 1 [32 65 57708]) fontified t) 4866 4874 (fontified t) 4874 4875 (face (rainbow-delimiters-depth-1-face) fontified t) 4875 4880 (face font-lock-string-face fontified t) 4880 4881 (face (rainbow-delimiters-depth-1-face) fontified t) 4881 4886 (fontified t) 4886 4888 (face font-lock-builtin-face fontified t) 4888 4889 (prettify-symbols-end 5021 prettify-symbols-start 5020 composition (0 1 [32 65 57708]) fontified t) 4889 4910 (fontified t) 4910 4911 (prettify-symbols-end 5043 prettify-symbols-start 5042 composition (0 1 [32 65 57708]) fontified t) 4911 4912 (fontified t) 4912 4916 (face font-lock-builtin-face fontified t) 4916 4917 (face (rainbow-delimiters-depth-1-face) fontified t) 4917 4920 (face font-lock-builtin-face fontified t) 4920 4925 (fontified t) 4925 4926 (face (rainbow-delimiters-depth-1-face) fontified t) 4926 4931 (fontified t) 4931 4943 (face font-lock-variable-name-face fontified t) 4943 4944 (fontified t) 4944 4945 (face font-lock-operator-face fontified t) 4945 4956 (fontified t) 4956 4957 (face (rainbow-delimiters-depth-1-face) fontified t) 4957 4962 (fontified t) 4962 4963 (face font-lock-operator-face fontified t) 4963 4970 (face font-lock-string-face fontified t) 4970 4971 (face (rainbow-delimiters-depth-1-face) fontified t) 4971 4974 (fontified t) 4974 4976 (face font-lock-comment-delimiter-face fontified t) 4976 4992 (face font-lock-comment-face fontified t) 4992 5009 (face font-lock-variable-name-face fontified t) 5009 5010 (fontified t) 5010 5011 (face font-lock-operator-face fontified t) 5011 5012 (fontified t) 5012 5013 (face font-lock-operator-face fontified t) 5013 5019 (fontified t) 5019 5021 (face font-lock-comment-delimiter-face fontified t) 5021 5078 (face font-lock-comment-face fontified t) 5078 5079 (fontified t) 5079 5081 (face font-lock-comment-delimiter-face fontified t) 5081 5111 (face font-lock-comment-face fontified t) 5111 5122 (face font-lock-variable-name-face fontified t) 5122 5123 (fontified t) 5123 5124 (face font-lock-operator-face fontified t) 5124 5125 (fontified t) 5125 5126 (face font-lock-operator-face fontified t) 5126 5132 (fontified t) 5132 5147 (face font-lock-variable-name-face fontified t) 5147 5148 (fontified t) 5148 5149 (face font-lock-operator-face fontified t) 5149 5150 (fontified t) 5150 5151 (face font-lock-operator-face fontified t) 5151 5157 (fontified t) 5157 5173 (face font-lock-variable-name-face fontified t) 5173 5174 (fontified t) 5174 5175 (face font-lock-operator-face fontified t) 5175 5176 (fontified t) 5176 5177 (face font-lock-operator-face fontified t) 5177 5183 (fontified t) 5183 5197 (face font-lock-variable-name-face fontified t) 5197 5198 (fontified t) 5198 5199 (face font-lock-operator-face fontified t) 5199 5200 (fontified t) 5200 5201 (face font-lock-operator-face fontified t) 5201 5207 (fontified t) 5207 5221 (face font-lock-variable-name-face fontified t) 5221 5222 (fontified t) 5222 5223 (face font-lock-operator-face fontified t) 5223 5224 (fontified t) 5224 5225 (face font-lock-operator-face fontified t) 5225 5233 (fontified t) 5233 5238 (face font-lock-keyword-face fontified t) 5238 5239 (fontified t) 5239 5248 (face font-lock-type-face fontified t) 5248 5249 (face (rainbow-delimiters-depth-1-face) fontified t) 5249 5258 (fontified t) 5258 5259 (face (rainbow-delimiters-depth-1-face) fontified t) 5259 5260 (prettify-symbols-end 5392 prettify-symbols-start 5391 composition (0 1 [32 65 57708]) fontified t) 5260 5265 (fontified t) 5265 5267 (face font-lock-doc-face fontified t) 5267 5268 (face font-lock-doc-face syntax-table (15) fontified t) 5268 5315 (face font-lock-doc-face fontified t) 5315 5316 (face font-lock-doc-face syntax-table (15) fontified t) 5316 5318 (face font-lock-doc-face fontified t) 5318 5328 (fontified t) 5328 5329 (prettify-symbols-end 5461 prettify-symbols-start 5460 composition (0 1 [32 65 57708]) fontified t) 5329 5330 (fontified t) 5330 5333 (face font-lock-builtin-face fontified t) 5333 5338 (fontified t) 5338 5340 (face font-lock-string-face fontified t) 5340 5341 (face font-lock-string-face syntax-table (15) fontified t) 5341 5370 (face font-lock-string-face fontified t) 5370 5371 (face font-lock-string-face syntax-table (15) fontified t) 5371 5373 (face font-lock-string-face fontified t) 5373 5386 (fontified t) 5386 5387 (prettify-symbols-end 5519 prettify-symbols-start 5518 composition (0 1 [32 65 57708]) fontified t) 5387 5388 (fontified t) 5388 5391 (face font-lock-builtin-face fontified t) 5391 5396 (fontified t) 5396 5398 (face font-lock-string-face fontified t) 5398 5399 (face font-lock-string-face syntax-table (15) fontified t) 5399 5506 (face font-lock-string-face fontified t) 5506 5507 (face font-lock-string-face syntax-table (15) fontified t) 5507 5509 (face font-lock-string-face fontified t) 5509 5519 (fontified t) 5519 5520 (prettify-symbols-end 5652 prettify-symbols-start 5651 composition (0 1 [32 65 57708]) fontified t) 5520 5525 (fontified t) 5525 5526 (face font-lock-operator-face fontified t) 5526 5527 (fontified t) 5527 5531 (face font-lock-constant-face fontified t) 5531 5532 (fontified t) 5532 5533 (face font-lock-operator-face fontified t) 5533 5534 (fontified t) 5534 5538 (face font-lock-constant-face fontified t) 5538 5543 (fontified t) 5543 5545 (face font-lock-doc-face fontified t) 5545 5546 (face font-lock-doc-face syntax-table (15) fontified t) 5546 5704 (face font-lock-doc-face fontified t) 5704 5705 (face font-lock-doc-face syntax-table (15) fontified t) 5705 5707 (face font-lock-doc-face fontified t) 5707 5713 (fontified t) 5713 5725 (face font-lock-variable-name-face fontified t) 5725 5726 (fontified t) 5726 5727 (face font-lock-operator-face fontified t) 5727 5738 (fontified t) 5738 5739 (face (rainbow-delimiters-depth-1-face) fontified t) 5739 5744 (fontified t) 5744 5745 (face font-lock-operator-face fontified t) 5745 5752 (face font-lock-string-face fontified t) 5752 5753 (face (rainbow-delimiters-depth-1-face) fontified t) 5753 5756 (fontified t) 5756 5761 (face font-lock-keyword-face fontified t) 5761 5762 (fontified t) 5762 5774 (face font-lock-type-face fontified t) 5774 5775 (face (rainbow-delimiters-depth-1-face) fontified t) 5775 5784 (fontified t) 5784 5785 (face (rainbow-delimiters-depth-1-face) fontified t) 5785 5786 (prettify-symbols-end 5918 prettify-symbols-start 5917 composition (0 1 [32 65 57708]) fontified t) 5786 5791 (fontified t) 5791 5793 (face font-lock-doc-face fontified t) 5793 5794 (face font-lock-doc-face syntax-table (15) fontified t) 5794 5851 (face font-lock-doc-face fontified t) 5851 5852 (face font-lock-doc-face syntax-table (15) fontified t) 5852 5854 (face font-lock-doc-face fontified t) 5854 5867 (fontified t) 5867 5868 (prettify-symbols-end 6000 prettify-symbols-start 5999 composition ((1 32 65 57708)) fontified t) 5868 5876 (fontified t) 5876 5877 (face (rainbow-delimiters-depth-1-face) fontified t) 5877 5882 (face font-lock-string-face fontified t) 5882 5883 (face (rainbow-delimiters-depth-1-face) fontified t) 5883 5888 (fontified t) 5888 5890 (face font-lock-builtin-face fontified t) 5890 5891 (prettify-symbols-end 6023 prettify-symbols-start 6022 composition ((1 32 65 57708)) fontified t) 5891 5892 (fontified t) 5892 5895 (face font-lock-builtin-face fontified t) 5895 5896 (fontified t) 5896 5897 (face font-lock-operator-face fontified t) 5897 5898 (fontified t) 5898 5901 (face font-lock-builtin-face fontified t) 5901 5911 (fontified t) 5911 5912 (prettify-symbols-end 6044 prettify-symbols-start 6043 composition ((1 32 65 57708)) fontified t) 5912 5927 (fontified t) 5927 5939 (face font-lock-variable-name-face fontified t) 5939 5940 (fontified t) 5940 5941 (face font-lock-operator-face fontified t) 5941 5952 (fontified t) 5952 5953 (face (rainbow-delimiters-depth-1-face) fontified t) 5953 5958 (fontified t) 5958 5959 (face font-lock-operator-face fontified t) 5959 5966 (face font-lock-string-face fontified t) 5966 5967 (face (rainbow-delimiters-depth-1-face) fontified t) 5967 5970 (fontified t) 5970 5975 (face font-lock-keyword-face fontified t) 5975 5976 (fontified t) 5976 5990 (face font-lock-type-face fontified t) 5990 5991 (face (rainbow-delimiters-depth-1-face) fontified t) 5991 6000 (fontified t) 6000 6001 (face (rainbow-delimiters-depth-2-face) fontified t) 6001 6016 (fontified t) 6016 6017 (face font-lock-operator-face fontified t) 6017 6038 (fontified t) 6038 6039 (face font-lock-operator-face fontified t) 6039 6056 (fontified t) 6056 6057 (face font-lock-operator-face fontified t) 6057 6070 (fontified t) 6070 6071 (face (rainbow-delimiters-depth-2-face) fontified t) 6071 6072 (face (rainbow-delimiters-depth-1-face) fontified t) 6072 6073 (prettify-symbols-end 6205 prettify-symbols-start 6204 composition (0 1 [32 65 57708]) fontified t) 6073 6078 (fontified t) 6078 6082 (face font-lock-keyword-face fontified t) 6082 6085 (fontified t) 6085 6090 (face font-lock-keyword-face fontified t) 6090 6091 (fontified t) 6091 6102 (face font-lock-type-face fontified t) 6102 6103 (face (rainbow-delimiters-depth-1-face) fontified t) 6103 6109 (fontified t) 6109 6110 (face (rainbow-delimiters-depth-1-face) fontified t) 6110 6111 (prettify-symbols-end 6243 prettify-symbols-start 6242 composition (0 1 [32 65 57708]) fontified t) 6111 6116 (fontified t) 6116 6118 (face font-lock-doc-face fontified t) 6118 6119 (face font-lock-doc-face syntax-table (15) fontified t) 6119 6173 (face font-lock-doc-face fontified t) 6173 6174 (face font-lock-doc-face syntax-table (15) fontified t) 6174 6176 (face font-lock-doc-face fontified t) 6176 6179 (fontified t) 6179 6184 (face font-lock-keyword-face fontified t) 6184 6185 (fontified t) 6185 6197 (face font-lock-type-face fontified t) 6197 6198 (face (rainbow-delimiters-depth-1-face) fontified t) 6198 6207 (fontified t) 6207 6208 (face (rainbow-delimiters-depth-1-face) fontified t) 6208 6209 (prettify-symbols-end 6341 prettify-symbols-start 6340 composition ((1 32 65 57708)) fontified t) 6209 6214 (fontified t) 6214 6216 (face font-lock-doc-face fontified t) 6216 6217 (face font-lock-doc-face syntax-table (15) fontified t) 6217 6277 (face font-lock-doc-face fontified t) 6277 6278 (face font-lock-doc-face syntax-table (15) fontified t) 6278 6280 (face font-lock-doc-face fontified t) 6280 6290 (fontified t) 6290 6291 (prettify-symbols-end 6423 prettify-symbols-start 6422 composition ((1 32 65 57708)) fontified t) 6291 6292 (fontified t) 6292 6295 (face font-lock-builtin-face fontified t) 6295 6300 (fontified t) 6300 6302 (face font-lock-string-face fontified t) 6302 6303 (face font-lock-string-face syntax-table (15) fontified t) 6303 6339 (face font-lock-string-face fontified t) 6339 6340 (face font-lock-string-face syntax-table (15) fontified t) 6340 6342 (face font-lock-string-face fontified t) 6342 6353 (fontified t) 6353 6354 (prettify-symbols-end 6486 prettify-symbols-start 6485 composition ((1 32 65 57708)) fontified t) 6354 6355 (fontified t) 6355 6358 (face font-lock-builtin-face fontified t) 6358 6359 (fontified t) 6359 6360 (face font-lock-operator-face fontified t) 6360 6361 (fontified t) 6361 6365 (face font-lock-constant-face fontified t) 6365 6366 (fontified t) 6366 6367 (face font-lock-operator-face fontified t) 6367 6368 (fontified t) 6368 6372 (face font-lock-constant-face fontified t) 6372 6377 (fontified t) 6377 6379 (face font-lock-doc-face fontified t) 6379 6380 (face font-lock-doc-face syntax-table (15) fontified t) 6380 6715 (face font-lock-doc-face fontified t) 6715 6716 (face font-lock-doc-face syntax-table (15) fontified t) 6716 6718 (face font-lock-doc-face fontified t) 6718 6721 (fontified t) 6721 6726 (face font-lock-keyword-face fontified t) 6726 6727 (fontified t) 6727 6741 (face font-lock-type-face fontified t) 6741 6742 (face (rainbow-delimiters-depth-1-face) fontified t) 6742 6754 (fontified t) 6754 6755 (face (rainbow-delimiters-depth-1-face) fontified t) 6755 6756 (prettify-symbols-end 6888 prettify-symbols-start 6887 composition (0 1 [32 65 57708]) fontified t) 6756 6761 (fontified t) 6761 6763 (face font-lock-doc-face fontified t) 6763 6764 (face font-lock-doc-face syntax-table (15) fontified t) 6764 6820 (face font-lock-doc-face fontified t) 6820 6821 (face font-lock-doc-face syntax-table (15) fontified t) 6821 6823 (face font-lock-doc-face fontified t) 6823 6836 (fontified t) 6836 6837 (prettify-symbols-end 6969 prettify-symbols-start 6968 composition (0 1 [32 65 57708]) fontified t) 6837 6838 (fontified t) 6838 6841 (face font-lock-builtin-face fontified t) 6841 6846 (fontified t) 6846 6858 (face font-lock-variable-name-face fontified t) 6858 6859 (fontified t) 6859 6860 (face font-lock-operator-face fontified t) 6860 6871 (fontified t) 6871 6872 (face (rainbow-delimiters-depth-1-face) fontified t) 6872 6877 (fontified t) 6877 6878 (face font-lock-operator-face fontified t) 6878 6885 (face font-lock-string-face fontified t) 6885 6886 (face (rainbow-delimiters-depth-1-face) fontified t) 6886 6889 (fontified t) 6889 6894 (face font-lock-keyword-face fontified t) 6894 6895 (fontified t) 6895 6910 (face font-lock-type-face fontified t) 6910 6911 (face (rainbow-delimiters-depth-1-face) fontified t) 6911 6920 (fontified t) 6920 6921 (face (rainbow-delimiters-depth-1-face) fontified t) 6921 6922 (prettify-symbols-end 7054 prettify-symbols-start 7053 composition (0 1 [32 65 57708]) fontified t) 6922 6927 (fontified t) 6927 6929 (face font-lock-doc-face fontified t) 6929 6930 (face font-lock-doc-face syntax-table (15) fontified t) 6930 6961 (face font-lock-doc-face fontified t) 6961 6962 (face font-lock-doc-face syntax-table (15) fontified t) 6962 6964 (face font-lock-doc-face fontified t) 6964 6981 (fontified t) 6981 6982 (prettify-symbols-end 7114 prettify-symbols-start 7113 composition (0 1 [32 65 57708]) fontified t) 6982 6983 (fontified t) 6983 6987 (face font-lock-builtin-face fontified t) 6987 6988 (fontified t) 6988 6989 (face font-lock-operator-face fontified t) 6989 6990 (fontified t) 6990 6994 (face font-lock-constant-face fontified t) 6994 6995 (fontified t) 6995 6996 (face font-lock-operator-face fontified t) 6996 6997 (fontified t) 6997 7001 (face font-lock-constant-face fontified t) 7001 7006 (fontified t) 7006 7008 (face font-lock-doc-face fontified t) 7008 7009 (face font-lock-doc-face syntax-table (15) fontified t) 7009 7081 (face font-lock-doc-face fontified t) 7081 7082 (face font-lock-doc-face syntax-table (15) fontified t) 7082 7084 (face font-lock-doc-face fontified t) 7084 7089 (fontified t) 7089 7101 (face font-lock-variable-name-face fontified t) 7101 7102 (fontified t) 7102 7103 (face font-lock-operator-face fontified t) 7103 7114 (fontified t) 7114 7115 (face (rainbow-delimiters-depth-1-face) fontified t) 7115 7120 (fontified t) 7120 7121 (face font-lock-operator-face fontified t) 7121 7128 (face font-lock-string-face fontified t) 7128 7129 (face (rainbow-delimiters-depth-1-face) fontified t) 7129 7132 (fontified t) 7132 7137 (face font-lock-keyword-face fontified t) 7137 7138 (fontified t) 7138 7156 (face font-lock-type-face fontified t) 7156 7157 (face (rainbow-delimiters-depth-1-face) fontified t) 7157 7166 (fontified t) 7166 7167 (face (rainbow-delimiters-depth-1-face) fontified t) 7167 7168 (prettify-symbols-end 7300 prettify-symbols-start 7299 composition (0 1 [32 65 57708]) fontified t) 7168 7173 (fontified t) 7173 7175 (face font-lock-doc-face fontified t) 7175 7176 (face font-lock-doc-face syntax-table (15) fontified t) 7176 7211 (face font-lock-doc-face fontified t) 7211 7212 (face font-lock-doc-face syntax-table (15) fontified t) 7212 7214 (face font-lock-doc-face fontified t) 7214 7220 (fontified t) 7220 7232 (face font-lock-variable-name-face fontified t) 7232 7233 (fontified t) 7233 7234 (face font-lock-operator-face fontified t) 7234 7245 (fontified t) 7245 7246 (face (rainbow-delimiters-depth-1-face) fontified t) 7246 7251 (fontified t) 7251 7252 (face font-lock-operator-face fontified t) 7252 7259 (face font-lock-string-face fontified t) 7259 7260 (face (rainbow-delimiters-depth-1-face) fontified t) 7260 7263 (fontified t) 7263 7268 (face font-lock-keyword-face fontified t) 7268 7269 (fontified t) 7269 7290 (face font-lock-type-face fontified t) 7290 7291 (face (rainbow-delimiters-depth-1-face) fontified t) 7291 7300 (fontified t) 7300 7301 (face (rainbow-delimiters-depth-1-face) fontified t) 7301 7302 (prettify-symbols-end 7434 prettify-symbols-start 7433 composition (0 1 [32 65 57708]) fontified t) 7302 7307 (fontified t) 7307 7309 (face font-lock-doc-face fontified t) 7309 7310 (face font-lock-doc-face syntax-table (15) fontified t) 7310 7348 (face font-lock-doc-face fontified t) 7348 7349 (face font-lock-doc-face syntax-table (15) fontified t) 7349 7351 (face font-lock-doc-face fontified t) 7351 7357 (fontified t) 7357 7369 (face font-lock-variable-name-face fontified t) 7369 7370 (fontified t) 7370 7371 (face font-lock-operator-face fontified t) 7371 7382 (fontified t) 7382 7383 (face (rainbow-delimiters-depth-1-face) fontified t) 7383 7388 (fontified t) 7388 7389 (face font-lock-operator-face fontified t) 7389 7396 (face font-lock-string-face fontified t) 7396 7397 (face (rainbow-delimiters-depth-1-face) fontified t) 7397 7400 (fontified t) 7400 7405 (face font-lock-keyword-face fontified t) 7405 7406 (fontified t) 7406 7424 (face font-lock-type-face fontified t) 7424 7425 (face (rainbow-delimiters-depth-1-face) fontified t) 7425 7434 (fontified t) 7434 7435 (face (rainbow-delimiters-depth-1-face) fontified t) 7435 7436 (prettify-symbols-end 7568 prettify-symbols-start 7567 composition (0 1 [32 65 57708]) fontified t) 7436 7441 (fontified t) 7441 7443 (face font-lock-doc-face fontified t) 7443 7444 (face font-lock-doc-face syntax-table (15) fontified t) 7444 7478 (face font-lock-doc-face fontified t) 7478 7479 (face font-lock-doc-face syntax-table (15) fontified t) 7479 7481 (face font-lock-doc-face fontified t) 7481 7499 (fontified t) 7499 7500 (prettify-symbols-end 7632 prettify-symbols-start 7631 composition (0 1 [32 65 57708]) fontified t) 7500 7501 (fontified t) 7501 7505 (face font-lock-builtin-face fontified t) 7505 7506 (face (rainbow-delimiters-depth-1-face) fontified t) 7506 7509 (face font-lock-builtin-face fontified t) 7509 7511 (fontified t) 7511 7515 (face font-lock-builtin-face fontified t) 7515 7516 (face (rainbow-delimiters-depth-2-face) fontified t) 7516 7519 (face font-lock-builtin-face fontified t) 7519 7524 (fontified t) 7524 7525 (face (rainbow-delimiters-depth-2-face) fontified t) 7525 7526 (face (rainbow-delimiters-depth-1-face) fontified t) 7526 7527 (fontified t) 7527 7528 (face font-lock-operator-face fontified t) 7528 7529 (fontified t) 7529 7533 (face font-lock-constant-face fontified t) 7533 7534 (fontified t) 7534 7535 (face font-lock-operator-face fontified t) 7535 7536 (fontified t) 7536 7540 (face font-lock-constant-face fontified t) 7540 7545 (fontified t) 7545 7547 (face font-lock-doc-face fontified t) 7547 7548 (face font-lock-doc-face syntax-table (15) fontified t) 7548 7613 (face font-lock-doc-face fontified t) 7613 7614 (face font-lock-doc-face syntax-table (15) fontified t) 7614 7616 (face font-lock-doc-face fontified t) 7616 7629 (fontified t) 7629 7630 (prettify-symbols-end 7762 prettify-symbols-start 7761 composition (0 1 [32 65 57708]) fontified t) 7630 7650 (fontified t) 7650 7651 (face font-lock-operator-face fontified t) 7651 7652 (fontified t) 7652 7656 (face font-lock-constant-face fontified t) 7656 7657 (fontified t) 7657 7658 (face font-lock-operator-face fontified t) 7658 7659 (fontified t) 7659 7663 (face font-lock-constant-face fontified t) 7663 7668 (fontified t) 7668 7670 (face font-lock-doc-face fontified t) 7670 7671 (face font-lock-doc-face syntax-table (15) fontified t) 7671 7723 (face font-lock-doc-face fontified t) 7723 7724 (face font-lock-doc-face syntax-table (15) fontified t) 7724 7726 (face font-lock-doc-face fontified t) 7726 7742 (fontified t) 7742 7743 (prettify-symbols-end 7875 prettify-symbols-start 7874 composition (0 1 [32 65 57708]) fontified t) 7743 7766 (fontified t) 7766 7767 (face font-lock-operator-face fontified t) 7767 7768 (fontified t) 7768 7772 (face font-lock-constant-face fontified t) 7772 7773 (fontified t) 7773 7774 (face font-lock-operator-face fontified t) 7774 7775 (fontified t) 7775 7779 (face font-lock-constant-face fontified t) 7779 7784 (fontified t) 7784 7786 (face font-lock-doc-face fontified t) 7786 7787 (face font-lock-doc-face syntax-table (15) fontified t) 7787 7844 (face font-lock-doc-face fontified t) 7844 7845 (face font-lock-doc-face syntax-table (15) fontified t) 7845 7847 (face font-lock-doc-face fontified t) 7847 7857 (fontified t) 7857 7858 (prettify-symbols-end 7990 prettify-symbols-start 7989 composition (0 1 [32 65 57708]) fontified t) 7858 7875 (fontified t) 7875 7876 (face font-lock-operator-face fontified t) 7876 7877 (fontified t) 7877 7881 (face font-lock-constant-face fontified t) 7881 7882 (fontified t) 7882 7883 (face font-lock-operator-face fontified t) 7883 7884 (fontified t) 7884 7888 (face font-lock-constant-face fontified t) 7888 7893 (fontified t) 7893 7895 (face font-lock-doc-face fontified t) 7895 7896 (face font-lock-doc-face syntax-table (15) fontified t) 7896 7941 (face font-lock-doc-face fontified t) 7941 7942 (face font-lock-doc-face syntax-table (15) fontified t) 7942 7944 (face font-lock-doc-face fontified t) 7944 7949 (fontified t) 7949 7961 (face font-lock-variable-name-face fontified t) 7961 7962 (fontified t) 7962 7963 (face font-lock-operator-face fontified t) 7963 7974 (fontified t) 7974 7975 (face (rainbow-delimiters-depth-1-face) fontified t) 7975 7980 (fontified t) 7980 7981 (face font-lock-operator-face fontified t) 7981 7988 (face font-lock-string-face fontified t) 7988 7989 (face (rainbow-delimiters-depth-1-face) fontified t) 7989 7992 (fontified t) 7992 7997 (face font-lock-keyword-face fontified t) 7997 7998 (fontified t) 7998 8015 (face font-lock-type-face fontified t) 8015 8016 (face (rainbow-delimiters-depth-1-face) fontified t) 8016 8025 (fontified t) 8025 8026 (face (rainbow-delimiters-depth-1-face) fontified t) 8026 8027 (prettify-symbols-end 8159 prettify-symbols-start 8158 composition (0 1 [32 65 57708]) fontified t) 8027 8032 (fontified t) 8032 8034 (face font-lock-doc-face fontified t) 8034 8035 (face font-lock-doc-face syntax-table (15) fontified t) 8035 8069 (face font-lock-doc-face fontified t) 8069 8070 (face font-lock-doc-face syntax-table (15) fontified t) 8070 8072 (face font-lock-doc-face fontified t) 8072 8089 (fontified t) 8089 8090 (prettify-symbols-end 8222 prettify-symbols-start 8221 composition (0 1 [32 65 57708]) fontified t) 8090 8091 (fontified t) 8091 8095 (face font-lock-builtin-face fontified t) 8095 8096 (fontified t) 8096 8097 (face font-lock-operator-face fontified t) 8097 8098 (fontified t) 8098 8102 (face font-lock-constant-face fontified t) 8102 8103 (fontified t) 8103 8104 (face font-lock-operator-face fontified t) 8104 8105 (fontified t) 8105 8109 (face font-lock-constant-face fontified t) 8109 8114 (fontified t) 8114 8116 (face font-lock-doc-face fontified t) 8116 8117 (face font-lock-doc-face syntax-table (15) fontified t) 8117 8191 (face font-lock-doc-face fontified t) 8191 8192 (face font-lock-doc-face syntax-table (15) fontified t) 8192 8194 (face font-lock-doc-face fontified t) 8194 8199 (fontified t) 8199 8211 (face font-lock-variable-name-face fontified t) 8211 8212 (fontified t) 8212 8213 (face font-lock-operator-face fontified t) 8213 8224 (fontified t) 8224 8225 (face (rainbow-delimiters-depth-1-face) fontified t) 8225 8230 (fontified t) 8230 8231 (face font-lock-operator-face fontified t) 8231 8238 (face font-lock-string-face fontified t) 8238 8239 (face (rainbow-delimiters-depth-1-face) fontified t) 8239 8242 (fontified t) 8242 8247 (face font-lock-keyword-face fontified t) 8247 8248 (fontified t) 8248 8267 (face font-lock-type-face fontified t) 8267 8268 (face (rainbow-delimiters-depth-1-face) fontified t) 8268 8277 (fontified t) 8277 8278 (face (rainbow-delimiters-depth-1-face) fontified t) 8278 8279 (prettify-symbols-end 8411 prettify-symbols-start 8410 composition (0 1 [32 65 57708]) fontified t) 8279 8284 (fontified t) 8284 8286 (face font-lock-doc-face fontified t) 8286 8287 (face font-lock-doc-face syntax-table (15) fontified t) 8287 8323 (face font-lock-doc-face fontified t) 8323 8324 (face font-lock-doc-face syntax-table (15) fontified t) 8324 8326 (face font-lock-doc-face fontified t) 8326 8341 (fontified t) 8341 8342 (prettify-symbols-end 8474 prettify-symbols-start 8473 composition (0 1 [32 65 57708]) fontified t) 8342 8343 (fontified t) 8343 8347 (face font-lock-builtin-face fontified t) 8347 8348 (fontified t) 8348 8349 (face font-lock-operator-face fontified t) 8349 8350 (fontified t) 8350 8354 (face font-lock-constant-face fontified t) 8354 8355 (fontified t) 8355 8356 (face font-lock-operator-face fontified t) 8356 8357 (fontified t) 8357 8361 (face font-lock-constant-face fontified t) 8361 8366 (fontified t) 8366 8368 (face font-lock-doc-face fontified t) 8368 8369 (face font-lock-doc-face syntax-table (15) fontified t) 8369 8430 (face font-lock-doc-face fontified t) 8430 8431 (face font-lock-doc-face syntax-table (15) fontified t) 8431 8433 (face font-lock-doc-face fontified t) 8433 8449 (fontified t) 8449 8450 (prettify-symbols-end 8582 prettify-symbols-start 8581 composition (0 1 [32 65 57708]) fontified t) 8450 8451 (fontified t) 8451 8455 (face font-lock-builtin-face fontified t) 8455 8456 (fontified t) 8456 8457 (face font-lock-operator-face fontified t) 8457 8458 (fontified t) 8458 8462 (face font-lock-constant-face fontified t) 8462 8463 (fontified t) 8463 8464 (face font-lock-operator-face fontified t) 8464 8465 (fontified t) 8465 8469 (face font-lock-constant-face fontified t) 8469 8474 (fontified t) 8474 8476 (face font-lock-doc-face fontified t) 8476 8477 (face font-lock-doc-face syntax-table (15) fontified t) 8477 8553 (face font-lock-doc-face fontified t) 8553 8554 (face font-lock-doc-face syntax-table (15) fontified t) 8554 8556 (face font-lock-doc-face fontified t) 8556 8561 (fontified t) 8561 8573 (face font-lock-variable-name-face fontified t) 8573 8574 (fontified t) 8574 8575 (face font-lock-operator-face fontified t) 8575 8586 (fontified t) 8586 8587 (face (rainbow-delimiters-depth-1-face) fontified t) 8587 8592 (fontified t) 8592 8593 (face font-lock-operator-face fontified t) 8593 8600 (face font-lock-string-face fontified t) 8600 8601 (face (rainbow-delimiters-depth-1-face) fontified t) 8601 8604 (fontified t) 8604 8609 (face font-lock-keyword-face fontified t) 8609 8610 (fontified t) 8610 8625 (face font-lock-type-face fontified t) 8625 8626 (face (rainbow-delimiters-depth-1-face) fontified t) 8626 8635 (fontified t) 8635 8636 (face (rainbow-delimiters-depth-1-face) fontified t) 8636 8637 (prettify-symbols-end 8769 prettify-symbols-start 8768 composition (0 1 [32 65 57708]) fontified t) 8637 8642 (fontified t) 8642 8644 (face font-lock-doc-face fontified t) 8644 8645 (face font-lock-doc-face syntax-table (15) fontified t) 8645 8677 (face font-lock-doc-face fontified t) 8677 8678 (face font-lock-doc-face syntax-table (15) fontified t) 8678 8680 (face font-lock-doc-face fontified t) 8680 8697 (fontified t) 8697 8698 (prettify-symbols-end 8830 prettify-symbols-start 8829 composition ((1 32 65 57708)) fontified t) 8698 8699 (fontified t) 8699 8703 (face font-lock-builtin-face fontified t) 8703 8704 (fontified t) 8704 8705 (face font-lock-operator-face fontified t) 8705 8706 (fontified t) 8706 8710 (face font-lock-constant-face fontified t) 8710 8711 (fontified t) 8711 8712 (face font-lock-operator-face fontified t) 8712 8713 (fontified t) 8713 8717 (face font-lock-constant-face fontified t) 8717 8722 (fontified t) 8722 8724 (face font-lock-doc-face fontified t) 8724 8725 (face font-lock-doc-face syntax-table (15) fontified t) 8725 8797 (face font-lock-doc-face fontified t) 8797 8798 (face font-lock-doc-face syntax-table (15) fontified t) 8798 8800 (face font-lock-doc-face fontified t) 8800 8805 (fontified t) 8805 8817 (face font-lock-variable-name-face fontified t) 8817 8818 (fontified t) 8818 8819 (face font-lock-operator-face fontified t) 8819 8830 (fontified t) 8830 8831 (face (rainbow-delimiters-depth-1-face) fontified t) 8831 8836 (fontified t) 8836 8837 (face font-lock-operator-face fontified t) 8837 8844 (face font-lock-string-face fontified t) 8844 8845 (face (rainbow-delimiters-depth-1-face) fontified t) 8845 8848 (fontified t) 8848 8853 (face font-lock-keyword-face fontified t) 8853 8854 (fontified t) 8854 8871 (face font-lock-type-face fontified t) 8871 8872 (face (rainbow-delimiters-depth-1-face) fontified t) 8872 8881 (fontified t) 8881 8882 (face (rainbow-delimiters-depth-1-face) fontified t) 8882 8883 (prettify-symbols-end 9015 prettify-symbols-start 9014 composition (0 1 [32 65 57708]) fontified t) 8883 8888 (fontified t) 8888 8890 (face font-lock-doc-face fontified t) 8890 8891 (face font-lock-doc-face syntax-table (15) fontified t) 8891 8925 (face font-lock-doc-face fontified t) 8925 8926 (face font-lock-doc-face syntax-table (15) fontified t) 8926 8928 (face font-lock-doc-face fontified t) 8928 8934 (fontified t) 8934 8946 (face font-lock-variable-name-face fontified t) 8946 8947 (fontified t) 8947 8948 (face font-lock-operator-face fontified t) 8948 8959 (fontified t) 8959 8960 (face (rainbow-delimiters-depth-1-face) fontified t) 8960 8965 (fontified t) 8965 8966 (face font-lock-operator-face fontified t) 8966 8973 (face font-lock-string-face fontified t) 8973 8974 (face (rainbow-delimiters-depth-1-face) fontified t) 8974 8977 (fontified t) 8977 8982 (face font-lock-keyword-face fontified t) 8982 8983 (fontified t) 8983 9004 (face font-lock-type-face fontified t) 9004 9005 (face (rainbow-delimiters-depth-1-face) fontified t) 9005 9014 (fontified t) 9014 9015 (face (rainbow-delimiters-depth-1-face) fontified t) 9015 9016 (prettify-symbols-end 9148 prettify-symbols-start 9147 composition (0 1 [32 65 57708]) fontified t) 9016 9021 (fontified t) 9021 9023 (face font-lock-doc-face fontified t) 9023 9024 (face font-lock-doc-face syntax-table (15) fontified t) 9024 9062 (face font-lock-doc-face fontified t) 9062 9063 (face font-lock-doc-face syntax-table (15) fontified t) 9063 9065 (face font-lock-doc-face fontified t) 9065 9071 (fontified t) 9071 9083 (face font-lock-variable-name-face fontified t) 9083 9084 (fontified t) 9084 9085 (face font-lock-operator-face fontified t) 9085 9096 (fontified t) 9096 9097 (face (rainbow-delimiters-depth-1-face) fontified t) 9097 9102 (fontified t) 9102 9103 (face font-lock-operator-face fontified t) 9103 9110 (face font-lock-string-face fontified t) 9110 9111 (face (rainbow-delimiters-depth-1-face) fontified t) 9111 9114 (fontified t) 9114 9119 (face font-lock-keyword-face fontified t) 9119 9120 (fontified t) 9120 9138 (face font-lock-type-face fontified t) 9138 9139 (face (rainbow-delimiters-depth-1-face) fontified t) 9139 9148 (fontified t) 9148 9149 (face (rainbow-delimiters-depth-1-face) fontified t) 9149 9150 (prettify-symbols-end 9282 prettify-symbols-start 9281 composition (0 1 [32 65 57708]) fontified t) 9150 9155 (fontified t) 9155 9157 (face font-lock-doc-face fontified t) 9157 9158 (face font-lock-doc-face syntax-table (15) fontified t) 9158 9197 (face font-lock-doc-face fontified t) 9197 9198 (face font-lock-doc-face syntax-table (15) fontified t) 9198 9200 (face font-lock-doc-face fontified t) 9200 9218 (fontified t) 9218 9219 (prettify-symbols-end 9351 prettify-symbols-start 9350 composition (0 1 [32 65 57708]) fontified t) 9219 9220 (fontified t) 9220 9224 (face font-lock-builtin-face fontified t) 9224 9225 (face (rainbow-delimiters-depth-1-face) fontified t) 9225 9228 (face font-lock-builtin-face fontified t) 9228 9230 (fontified t) 9230 9234 (face font-lock-builtin-face fontified t) 9234 9235 (face (rainbow-delimiters-depth-2-face) fontified t) 9235 9238 (face font-lock-builtin-face fontified t) 9238 9243 (fontified t) 9243 9244 (face (rainbow-delimiters-depth-2-face) fontified t) 9244 9245 (face (rainbow-delimiters-depth-1-face) fontified t) 9245 9246 (fontified t) 9246 9247 (face font-lock-operator-face fontified t) 9247 9248 (fontified t) 9248 9252 (face font-lock-constant-face fontified t) 9252 9253 (fontified t) 9253 9254 (face font-lock-operator-face fontified t) 9254 9255 (fontified t) 9255 9259 (face font-lock-constant-face fontified t) 9259 9264 (fontified t) 9264 9266 (face font-lock-doc-face fontified t) 9266 9267 (face font-lock-doc-face syntax-table (15) fontified t) 9267 9332 (face font-lock-doc-face fontified t) 9332 9333 (face font-lock-doc-face syntax-table (15) fontified t) 9333 9335 (face font-lock-doc-face fontified t) 9335 9347 (fontified t) 9347 9348 (prettify-symbols-end 9480 prettify-symbols-start 9479 composition (0 1 [32 65 57708]) fontified t) 9348 9367 (fontified t) 9367 9368 (face font-lock-operator-face fontified t) 9368 9369 (fontified t) 9369 9373 (face font-lock-constant-face fontified t) 9373 9374 (fontified t) 9374 9375 (face font-lock-operator-face fontified t) 9375 9376 (fontified t) 9376 9380 (face font-lock-constant-face fontified t) 9380 9385 (fontified t) 9385 9387 (face font-lock-doc-face fontified t) 9387 9388 (face font-lock-doc-face syntax-table (15) fontified t) 9388 9454 (face font-lock-doc-face fontified t) 9454 9455 (face font-lock-doc-face syntax-table (15) fontified t) 9455 9457 (face font-lock-doc-face fontified t) 9457 9469 (fontified t) 9469 9470 (prettify-symbols-end 9602 prettify-symbols-start 9601 composition (0 1 [32 65 57708]) fontified t) 9470 9489 (fontified t) 9489 9490 (face font-lock-operator-face fontified t) 9490 9491 (fontified t) 9491 9495 (face font-lock-constant-face fontified t) 9495 9496 (fontified t) 9496 9497 (face font-lock-operator-face fontified t) 9497 9498 (fontified t) 9498 9502 (face font-lock-constant-face fontified t) 9502 9507 (fontified t) 9507 9509 (face font-lock-doc-face fontified t) 9509 9510 (face font-lock-doc-face syntax-table (15) fontified t) 9510 9560 (face font-lock-doc-face fontified t) 9560 9561 (face font-lock-doc-face syntax-table (15) fontified t) 9561 9563 (face font-lock-doc-face fontified t) 9563 9577 (fontified t) 9577 9578 (prettify-symbols-end 9710 prettify-symbols-start 9709 composition (0 1 [32 65 57708]) fontified t) 9578 9599 (fontified t) 9599 9600 (face font-lock-operator-face fontified t) 9600 9601 (fontified t) 9601 9605 (face font-lock-constant-face fontified t) 9605 9606 (fontified t) 9606 9607 (face font-lock-operator-face fontified t) 9607 9608 (fontified t) 9608 9612 (face font-lock-constant-face fontified t) 9612 9617 (fontified t) 9617 9619 (face font-lock-doc-face fontified t) 9619 9620 (face font-lock-doc-face syntax-table (15) fontified t) 9620 9671 (face font-lock-doc-face fontified t) 9671 9672 (face font-lock-doc-face syntax-table (15) fontified t) 9672 9674 (face font-lock-doc-face fontified t) 9674 9684 (fontified t) 9684 9685 (prettify-symbols-end 9817 prettify-symbols-start 9816 composition (0 1 [32 65 57708]) fontified t) 9685 9702 (fontified t) 9702 9703 (face font-lock-operator-face fontified t) 9703 9704 (fontified t) 9704 9708 (face font-lock-constant-face fontified t) 9708 9709 (fontified t) 9709 9710 (face font-lock-operator-face fontified t) 9710 9711 (fontified t) 9711 9715 (face font-lock-constant-face fontified t) 9715 9720 (fontified t) 9720 9722 (face font-lock-doc-face fontified t) 9722 9723 (face font-lock-doc-face syntax-table (15) fontified t) 9723 9770 (face font-lock-doc-face fontified t) 9770 9771 (face font-lock-doc-face syntax-table (15) fontified t) 9771 9773 (face font-lock-doc-face fontified t) 9773 9789 (fontified t) 9789 9790 (prettify-symbols-end 9922 prettify-symbols-start 9921 composition (0 1 [32 65 57708]) fontified t) 9790 9813 (fontified t) 9813 9814 (face font-lock-operator-face fontified t) 9814 9815 (fontified t) 9815 9819 (face font-lock-constant-face fontified t) 9819 9820 (fontified t) 9820 9821 (face font-lock-operator-face fontified t) 9821 9822 (fontified t) 9822 9826 (face font-lock-constant-face fontified t) 9826 9831 (fontified t) 9831 9833 (face font-lock-doc-face fontified t) 9833 9834 (face font-lock-doc-face syntax-table (15) fontified t) 9834 9916 (face font-lock-doc-face fontified t) 9916 9917 (face font-lock-doc-face syntax-table (15) fontified t) 9917 9919 (face font-lock-doc-face fontified t) 9919 9924 (fontified t) 9924 9936 (face font-lock-variable-name-face fontified t) 9936 9937 (fontified t) 9937 9938 (face font-lock-operator-face fontified t) 9938 9949 (fontified t) 9949 9950 (face (rainbow-delimiters-depth-1-face) fontified t) 9950 9955 (fontified t) 9955 9956 (face font-lock-operator-face fontified t) 9956 9963 (face font-lock-string-face fontified t) 9963 9964 (face (rainbow-delimiters-depth-1-face) fontified t) 9964 9967 (fontified t) 9967 9972 (face font-lock-keyword-face fontified t) 9972 9973 (fontified t) 9973 9996 (face font-lock-type-face fontified t) 9996 9997 (face (rainbow-delimiters-depth-1-face) fontified t) 9997 10010 (fontified t) 10010 10011 (face (rainbow-delimiters-depth-1-face) fontified t) 10011 10012 (prettify-symbols-end 10144 prettify-symbols-start 10143 composition (0 1 [32 65 57708]) fontified t) 10012 10017 (fontified t) 10017 10019 (face font-lock-doc-face fontified t) 10019 10020 (face font-lock-doc-face syntax-table (15) fontified t) 10020 10058 (face font-lock-doc-face fontified t) 10058 10059 (face font-lock-doc-face syntax-table (15) fontified t) 10059 10061 (face font-lock-doc-face fontified t) 10061 10082 (fontified t) 10082 10083 (prettify-symbols-end 10215 prettify-symbols-start 10214 composition (0 1 [32 65 57708]) fontified t) 10083 10084 (fontified t) 10084 10087 (face font-lock-builtin-face fontified t) 10087 10088 (fontified t) 10088 10089 (face font-lock-operator-face fontified t) 10089 10090 (fontified t) 10090 10093 (face font-lock-builtin-face fontified t) 10093 10098 (fontified t) 10098 10100 (face font-lock-string-face fontified t) 10100 10101 (face font-lock-string-face syntax-table (15) fontified t) 10101 10175 (face font-lock-string-face fontified t) 10175 10176 (face font-lock-string-face syntax-table (15) fontified t) 10176 10178 (face font-lock-string-face fontified t) 10178 10195 (fontified t) 10195 10196 (prettify-symbols-end 10328 prettify-symbols-start 10327 composition (0 1 [32 65 57708]) fontified t) 10196 10230 (fontified t) 10230 10231 (prettify-symbols-end 10363 prettify-symbols-start 10362 composition (0 1 [32 65 57708]) fontified t) 10231 10251 (fontified t) 10251 10263 (face font-lock-variable-name-face fontified t) 10263 10264 (fontified t) 10264 10265 (face font-lock-operator-face fontified t) 10265 10276 (fontified t) 10276 10277 (face (rainbow-delimiters-depth-1-face) fontified t) 10277 10282 (fontified t) 10282 10283 (face font-lock-operator-face fontified t) 10283 10290 (face font-lock-string-face fontified t) 10290 10291 (face (rainbow-delimiters-depth-1-face) fontified t) 10291 10294 (fontified t) 10294 10299 (face font-lock-keyword-face fontified t) 10299 10300 (fontified t) 10300 10317 (face font-lock-type-face fontified t) 10317 10318 (face (rainbow-delimiters-depth-1-face) fontified t) 10318 10325 (fontified t) 10325 10326 (face (rainbow-delimiters-depth-2-face) fontified t) 10326 10358 (fontified t) 10358 10359 (face (rainbow-delimiters-depth-3-face) fontified t) 10359 10371 (face font-lock-string-face fontified t) 10371 10372 (face (rainbow-delimiters-depth-3-face) fontified t) 10372 10373 (face (rainbow-delimiters-depth-2-face) fontified t) 10373 10374 (face (rainbow-delimiters-depth-1-face) fontified t) 10374 10375 (prettify-symbols-end 10507 prettify-symbols-start 10506 composition (0 1 [32 65 57708]) fontified t) 10375 10380 (fontified t) 10380 10382 (face font-lock-doc-face fontified t) 10382 10383 (face font-lock-doc-face syntax-table (15) fontified t) 10383 10506 (face font-lock-doc-face fontified t) 10506 10507 (face font-lock-doc-face syntax-table (15) fontified t) 10507 10509 (face font-lock-doc-face fontified t) 10509 10521 (fontified t) 10521 10522 (prettify-symbols-end 10654 prettify-symbols-start 10653 composition (0 1 [32 65 57708]) fontified t) 10522 10530 (fontified t) 10530 10531 (face (rainbow-delimiters-depth-1-face) fontified t) 10531 10543 (face font-lock-string-face fontified t) 10543 10544 (face (rainbow-delimiters-depth-1-face) fontified t) 10544 10555 (fontified t) 10555 10556 (prettify-symbols-end 10688 prettify-symbols-start 10687 composition (0 1 [32 65 57708]) fontified t) 10556 10583 (fontified t) 10583 10588 (face font-lock-keyword-face fontified t) 10588 10589 (fontified t) 10589 10605 (face font-lock-type-face fontified t) 10605 10606 (face (rainbow-delimiters-depth-1-face) fontified t) 10606 10612 (fontified t) 10612 10613 (face (rainbow-delimiters-depth-1-face) fontified t) 10613 10614 (prettify-symbols-end 10746 prettify-symbols-start 10745 composition (0 1 [32 65 57708]) fontified t) 10614 10619 (fontified t) 10619 10621 (face font-lock-doc-face fontified t) 10621 10622 (face font-lock-doc-face syntax-table (15) fontified t) 10622 10699 (face font-lock-doc-face fontified t) 10699 10700 (face font-lock-doc-face syntax-table (15) fontified t) 10700 10702 (face font-lock-doc-face fontified t) 10702 10723 (fontified t) 10723 10724 (prettify-symbols-end 10856 prettify-symbols-start 10855 composition (0 1 [32 65 57708]) fontified t) 10724 10725 (fontified t) 10725 10728 (face font-lock-builtin-face fontified t) 10728 10729 (fontified t) 10729 10730 (face font-lock-operator-face fontified t) 10730 10731 (fontified t) 10731 10734 (face font-lock-builtin-face fontified t) 10734 10739 (fontified t) 10739 10741 (face font-lock-string-face fontified t) 10741 10742 (face font-lock-string-face syntax-table (15) fontified t) 10742 10813 (face font-lock-string-face fontified t) 10813 10814 (face font-lock-string-face syntax-table (15) fontified t) 10814 10816 (face font-lock-string-face fontified t) 10816 10833 (fontified t) 10833 10834 (prettify-symbols-end 10966 prettify-symbols-start 10965 composition (0 1 [32 65 57708]) fontified t) 10834 10868 (fontified t) 10868 10869 (prettify-symbols-end 11001 prettify-symbols-start 11000 composition (0 1 [32 65 57708]) fontified t) 10869 10901 (fontified t) 10901 10902 (prettify-symbols-end 11034 prettify-symbols-start 11033 composition (0 1 [32 65 57708]) fontified t) 10902 10903 (fontified t) 10903 10906 (face font-lock-builtin-face fontified t) 10906 10907 (fontified t) 10907 10908 (face font-lock-operator-face fontified t) 10908 10909 (fontified t) 10909 10913 (face font-lock-constant-face fontified t) 10913 10914 (fontified t) 10914 10915 (face font-lock-operator-face fontified t) 10915 10916 (fontified t) 10916 10920 (face font-lock-constant-face fontified t) 10920 10925 (fontified t) 10925 10927 (face font-lock-doc-face fontified t) 10927 10928 (face font-lock-doc-face syntax-table (15) fontified t) 10928 10991 (face font-lock-doc-face fontified t) 10991 10992 (face font-lock-doc-face syntax-table (15) fontified t) 10992 10994 (face font-lock-doc-face fontified t) 10994 10997 (fontified t) 10997 11002 (face font-lock-keyword-face fontified t) 11002 11003 (fontified t) 11003 11026 (face font-lock-type-face fontified t) 11026 11027 (face (rainbow-delimiters-depth-1-face) fontified t) 11027 11039 (fontified t) 11039 11040 (face (rainbow-delimiters-depth-2-face) fontified t) 11040 11059 (fontified t) 11059 11060 (face font-lock-operator-face fontified t) 11060 11061 (fontified t) 11061 11065 (face font-lock-constant-face fontified t) 11065 11074 (fontified t) 11074 11075 (face (rainbow-delimiters-depth-3-face) fontified t) 11075 11102 (face font-lock-string-face fontified t) 11102 11103 (face (rainbow-delimiters-depth-3-face) fontified t) 11103 11104 (face (rainbow-delimiters-depth-2-face) fontified t) 11104 11105 (face (rainbow-delimiters-depth-1-face) fontified t) 11105 11106 (prettify-symbols-end 11238 prettify-symbols-start 11237 composition (0 1 [32 65 57708]) fontified t) 11106 11111 (fontified t) 11111 11113 (face font-lock-doc-face fontified t) 11113 11114 (face font-lock-doc-face syntax-table (15) fontified t) 11114 11218 (face font-lock-doc-face fontified t) 11218 11219 (face font-lock-doc-face syntax-table (15) fontified t) 11219 11221 (face font-lock-doc-face fontified t) 11221 11233 (fontified t) 11233 11234 (prettify-symbols-end 11366 prettify-symbols-start 11365 composition (0 1 [32 65 57708]) fontified t) 11234 11242 (fontified t) 11242 11243 (face (rainbow-delimiters-depth-1-face) fontified t) 11243 11270 (face font-lock-string-face fontified t) 11270 11271 (face (rainbow-delimiters-depth-1-face) fontified t) 11271 11282 (fontified t) 11282 11283 (prettify-symbols-end 11415 prettify-symbols-start 11414 composition (0 1 [32 65 57708]) fontified t) 11283 11303 (fontified t) 11303 11304 (face font-lock-operator-face fontified t) 11304 11305 (fontified t) 11305 11309 (face font-lock-constant-face fontified t) 11309 11310 (fontified t) 11310 11311 (face font-lock-operator-face fontified t) 11311 11312 (fontified t) 11312 11316 (face font-lock-constant-face fontified t) 11316 11319 (fontified t) 11319 11324 (face font-lock-keyword-face fontified t) 11324 11325 (fontified t) 11325 11336 (face font-lock-type-face fontified t) 11336 11337 (face (rainbow-delimiters-depth-1-face) fontified t) 11337 11344 (fontified t) 11344 11345 (face (rainbow-delimiters-depth-2-face) fontified t) 11345 11359 (fontified t) 11359 11360 (face font-lock-operator-face fontified t) 11360 11361 (fontified t) 11361 11365 (face font-lock-constant-face fontified t) 11365 11374 (fontified t) 11374 11375 (face (rainbow-delimiters-depth-3-face) fontified t) 11375 11381 (face font-lock-string-face fontified t) 11381 11382 (face (rainbow-delimiters-depth-3-face) fontified t) 11382 11383 (face (rainbow-delimiters-depth-2-face) fontified t) 11383 11384 (face (rainbow-delimiters-depth-1-face) fontified t) 11384 11385 (prettify-symbols-end 11517 prettify-symbols-start 11516 composition (0 1 [32 65 57708]) fontified t) 11385 11390 (fontified t) 11390 11392 (face font-lock-doc-face fontified t) 11392 11393 (face font-lock-doc-face syntax-table (15) fontified t) 11393 11503 (face font-lock-doc-face fontified t) 11503 11504 (face font-lock-doc-face syntax-table (15) fontified t) 11504 11506 (face font-lock-doc-face fontified t) 11506 11518 (fontified t) 11518 11519 (prettify-symbols-end 11651 prettify-symbols-start 11650 composition (0 1 [32 65 57708]) fontified t) 11519 11527 (fontified t) 11527 11528 (face (rainbow-delimiters-depth-1-face) fontified t) 11528 11534 (face font-lock-string-face fontified t) 11534 11535 (face (rainbow-delimiters-depth-1-face) fontified t) 11535 11546 (fontified t) 11546 11547 (prettify-symbols-end 11679 prettify-symbols-start 11678 composition (0 1 [32 65 57708]) fontified t) 11547 11562 (fontified t) 11562 11563 (face font-lock-operator-face fontified t) 11563 11564 (fontified t) 11564 11568 (face font-lock-constant-face fontified t) 11568 11569 (fontified t) 11569 11570 (face font-lock-operator-face fontified t) 11570 11571 (fontified t) 11571 11575 (face font-lock-constant-face fontified t) 11575 11578 (fontified t) 11578 11583 (face font-lock-keyword-face fontified t) 11583 11584 (fontified t) 11584 11610 (face font-lock-type-face fontified t) 11610 11611 (face (rainbow-delimiters-depth-1-face) fontified t) 11611 11629 (fontified t) 11629 11630 (face (rainbow-delimiters-depth-1-face) fontified t) 11630 11631 (prettify-symbols-end 11763 prettify-symbols-start 11762 composition (0 1 [32 65 57708]) fontified t) 11631 11636 (fontified t) 11636 11638 (face font-lock-doc-face fontified t) 11638 11639 (face font-lock-doc-face syntax-table (15) fontified t) 11639 11677 (face font-lock-doc-face fontified t) 11677 11678 (face font-lock-doc-face syntax-table (15) fontified t) 11678 11680 (face font-lock-doc-face fontified t) 11680 11699 (fontified t) 11699 11700 (prettify-symbols-end 11832 prettify-symbols-start 11831 composition (0 1 [32 65 57708]) fontified t) 11700 11719 (fontified t) 11719 11721 (face font-lock-string-face fontified t) 11721 11722 (face font-lock-string-face syntax-table (15) fontified t) 11722 11867 (face font-lock-string-face fontified t) 11867 11868 (face font-lock-string-face syntax-table (15) fontified t) 11868 11870 (face font-lock-string-face fontified t) 11870 11883 (fontified t) 11883 11884 (prettify-symbols-end 12016 prettify-symbols-start 12015 composition (0 1 [32 65 57708]) fontified t) 11884 11885 (fontified t) 11885 11890 (face font-lock-builtin-face fontified t) 11890 11895 (fontified t) 11895 11897 (face font-lock-string-face fontified t) 11897 11898 (face font-lock-string-face syntax-table (15) fontified t) 11898 12014 (face font-lock-string-face fontified t) 12014 12015 (face font-lock-string-face syntax-table (15) fontified t) 12015 12017 (face font-lock-string-face fontified t) 12017 12027 (fontified t) 12027 12028 (prettify-symbols-end 12160 prettify-symbols-start 12159 composition (0 1 [32 65 57708]) fontified t) 12028 12029 (fontified t) 12029 12034 (face font-lock-builtin-face fontified t) 12034 12035 (fontified t) 12035 12036 (face font-lock-operator-face fontified t) 12036 12037 (fontified t) 12037 12041 (face font-lock-constant-face fontified t) 12041 12042 (fontified t) 12042 12043 (face font-lock-operator-face fontified t) 12043 12044 (fontified t) 12044 12048 (face font-lock-constant-face fontified t) 12048 12053 (fontified t) 12053 12055 (face font-lock-doc-face fontified t) 12055 12056 (face font-lock-doc-face syntax-table (15) fontified t) 12056 12128 (face font-lock-doc-face fontified t) 12128 12129 (face font-lock-doc-face syntax-table (15) fontified t) 12129 12131 (face font-lock-doc-face fontified t) 12131 12143 (fontified t) 12143 12144 (prettify-symbols-end 12276 prettify-symbols-start 12275 composition (0 1 [32 65 57708]) fontified t) 12144 12145 (fontified t) 12145 12148 (face font-lock-builtin-face fontified t) 12148 12149 (fontified t) 12149 12150 (face font-lock-operator-face fontified t) 12150 12151 (fontified t) 12151 12155 (face font-lock-constant-face fontified t) 12155 12156 (fontified t) 12156 12157 (face font-lock-operator-face fontified t) 12157 12158 (fontified t) 12158 12162 (face font-lock-constant-face fontified t) 12162 12167 (fontified t) 12167 12169 (face font-lock-doc-face fontified t) 12169 12170 (face font-lock-doc-face syntax-table (15) fontified t) 12170 12278 (face font-lock-doc-face fontified t) 12278 12279 (face font-lock-doc-face syntax-table (15) fontified t) 12279 12281 (face font-lock-doc-face fontified t) 12281 12286 (fontified t) 12286 12298 (face font-lock-variable-name-face fontified t) 12298 12299 (fontified t) 12299 12300 (face font-lock-operator-face fontified t) 12300 12311 (fontified t) 12311 12312 (face (rainbow-delimiters-depth-1-face) fontified t) 12312 12317 (fontified t) 12317 12318 (face font-lock-operator-face fontified t) 12318 12325 (face font-lock-string-face fontified t) 12325 12326 (face (rainbow-delimiters-depth-1-face) fontified t) 12326 12329 (fontified t) 12329 12334 (face font-lock-keyword-face fontified t) 12334 12335 (fontified t) 12335 12355 (face font-lock-type-face fontified t) 12355 12356 (face (rainbow-delimiters-depth-1-face) fontified t) 12356 12368 (fontified t) 12368 12369 (face (rainbow-delimiters-depth-2-face) fontified t) 12369 12404 (fontified t) 12404 12405 (face (rainbow-delimiters-depth-3-face) fontified t) 12405 12429 (face font-lock-string-face fontified t) 12429 12430 (face (rainbow-delimiters-depth-3-face) fontified t) 12430 12431 (face (rainbow-delimiters-depth-2-face) fontified t) 12431 12432 (face (rainbow-delimiters-depth-1-face) fontified t) 12432 12433 (prettify-symbols-end 12565 prettify-symbols-start 12564 composition (0 1 [32 65 57708]) fontified t) 12433 12438 (fontified t) 12438 12440 (face font-lock-doc-face fontified t) 12440 12441 (face font-lock-doc-face syntax-table (15) fontified t) 12441 12559 (face font-lock-doc-face fontified t) 12559 12560 (face font-lock-doc-face syntax-table (15) fontified t) 12560 12562 (face font-lock-doc-face fontified t) 12562 12574 (fontified t) 12574 12575 (prettify-symbols-end 12707 prettify-symbols-start 12706 composition (0 1 [32 65 57708]) fontified t) 12575 12583 (fontified t) 12583 12584 (face (rainbow-delimiters-depth-1-face) fontified t) 12584 12608 (face font-lock-string-face fontified t) 12608 12609 (face (rainbow-delimiters-depth-1-face) fontified t) 12609 12620 (fontified t) 12620 12621 (prettify-symbols-end 12753 prettify-symbols-start 12752 composition (0 1 [32 65 57708]) fontified t) 12621 12651 (fontified t) 12651 12656 (face font-lock-keyword-face fontified t) 12656 12657 (fontified t) 12657 12677 (face font-lock-type-face fontified t) 12677 12678 (face (rainbow-delimiters-depth-1-face) fontified t) 12678 12689 (fontified t) 12689 12690 (face (rainbow-delimiters-depth-2-face) fontified t) 12690 12697 (fontified t) 12697 12698 (face (rainbow-delimiters-depth-3-face) fontified t) 12698 12714 (face font-lock-string-face fontified t) 12714 12715 (face (rainbow-delimiters-depth-3-face) fontified t) 12715 12716 (face (rainbow-delimiters-depth-2-face) fontified t) 12716 12717 (face (rainbow-delimiters-depth-1-face) fontified t) 12717 12718 (prettify-symbols-end 12850 prettify-symbols-start 12849 composition (0 1 [32 65 57708]) fontified t) 12718 12723 (fontified t) 12723 12725 (face font-lock-doc-face fontified t) 12725 12726 (face font-lock-doc-face syntax-table (15) fontified t) 12726 12793 (face font-lock-doc-face fontified t) 12793 12794 (face font-lock-doc-face syntax-table (15) fontified t) 12794 12796 (face font-lock-doc-face fontified t) 12796 12808 (fontified t) 12808 12809 (prettify-symbols-end 12941 prettify-symbols-start 12940 composition (0 1 [32 65 57708]) fontified t) 12809 12817 (fontified t) 12817 12818 (face (rainbow-delimiters-depth-1-face) fontified t) 12818 12834 (face font-lock-string-face fontified t) 12834 12835 (face (rainbow-delimiters-depth-1-face) fontified t) 12835 12838 (fontified t) 12838 12843 (face font-lock-keyword-face fontified t) 12843 12844 (fontified t) 12844 12855 (face font-lock-type-face fontified t) 12855 12856 (face (rainbow-delimiters-depth-1-face) fontified t) 12856 12865 (fontified t) 12865 12866 (face (rainbow-delimiters-depth-1-face) fontified t) 12866 12867 (prettify-symbols-end 12999 prettify-symbols-start 12998 composition (0 1 [32 65 57708]) fontified t) 12867 12880 (fontified t) 12880 12881 (prettify-symbols-end 13013 prettify-symbols-start 13012 composition (0 1 [32 65 57708]) fontified t) 12881 12882 (fontified t) 12882 12886 (face font-lock-builtin-face fontified t) 12886 12887 (face (rainbow-delimiters-depth-1-face) fontified t) 12887 12891 (fontified t) 12891 12892 (face (rainbow-delimiters-depth-1-face) fontified t) 12892 12893 (fontified t) 12893 12894 (face font-lock-operator-face fontified t) 12894 12895 (fontified t) 12895 12899 (face font-lock-constant-face fontified t) 12899 12900 (fontified t) 12900 12901 (face font-lock-operator-face fontified t) 12901 12902 (fontified t) 12902 12906 (face font-lock-constant-face fontified t) 12906 12919 (fontified t) 12919 12920 (prettify-symbols-end 13052 prettify-symbols-start 13051 composition (0 1 [32 65 57708]) fontified t) 12920 12930 (fontified t) 12930 12931 (face (rainbow-delimiters-depth-1-face) fontified t) 12931 12936 (face font-lock-builtin-face fontified t) 12936 12943 (fontified t) 12943 12944 (face (rainbow-delimiters-depth-2-face) fontified t) 12944 12946 (fontified t) 12946 12947 (face font-lock-operator-face fontified t) 12947 12954 (fontified t) 12954 12955 (face font-lock-operator-face fontified t) 12955 12958 (fontified t) 12958 12959 (face (rainbow-delimiters-depth-2-face) fontified t) 12959 12960 (face (rainbow-delimiters-depth-1-face) fontified t) 12960 12961 (fontified t) 12961 12962 (face font-lock-operator-face fontified t) 12962 12963 (fontified t) 12963 12967 (face font-lock-constant-face fontified t) 12967 12968 (fontified t) 12968 12969 (face font-lock-operator-face fontified t) 12969 12970 (fontified t) 12970 12974 (face font-lock-constant-face fontified t) 12974 12979 (fontified t) 12979 12991 (face font-lock-variable-name-face fontified t) 12991 12992 (fontified t) 12992 12993 (face font-lock-operator-face fontified t) 12993 13004 (fontified t) 13004 13005 (face (rainbow-delimiters-depth-1-face) fontified t) 13005 13010 (fontified t) 13010 13011 (face font-lock-operator-face fontified t) 13011 13018 (face font-lock-string-face fontified t) 13018 13019 (face (rainbow-delimiters-depth-1-face) fontified t) 13019 13022 (fontified t) 13022 13027 (face font-lock-keyword-face fontified t) 13027 13028 (fontified t) 13028 13036 (face font-lock-type-face fontified t) 13036 13037 (face (rainbow-delimiters-depth-1-face) fontified t) 13037 13049 (fontified t) 13049 13050 (face (rainbow-delimiters-depth-1-face) fontified t) 13050 13051 (prettify-symbols-end 13183 prettify-symbols-start 13182 composition (0 1 [32 65 57708]) fontified t) 13051 13056 (fontified t) 13056 13058 (face font-lock-doc-face fontified t) 13058 13059 (face font-lock-doc-face syntax-table (15) fontified t) 13059 13114 (face font-lock-doc-face fontified t) 13114 13115 (face font-lock-doc-face syntax-table (15) fontified t) 13115 13117 (face font-lock-doc-face fontified t) 13117 13126 (fontified t) 13126 13127 (prettify-symbols-end 13259 prettify-symbols-start 13258 composition (0 1 [32 65 57708]) fontified t) 13127 13137 (fontified t) 13137 13138 (face (rainbow-delimiters-depth-1-face) fontified t) 13138 13160 (fontified t) 13160 13161 (face (rainbow-delimiters-depth-2-face) fontified t) 13161 13174 (fontified t) 13174 13175 (face font-lock-operator-face fontified t) 13175 13180 (face font-lock-constant-face fontified t) 13180 13181 (face (rainbow-delimiters-depth-2-face) fontified t) 13181 13182 (face (rainbow-delimiters-depth-1-face) fontified t) 13182 13187 (fontified t) 13187 13189 (face font-lock-string-face fontified t) 13189 13190 (face font-lock-string-face syntax-table (15) fontified t) 13190 13215 (face font-lock-string-face fontified t) 13215 13216 (face font-lock-string-face syntax-table (15) fontified t) 13216 13218 (face font-lock-string-face fontified t) 13218 13234 (fontified t) 13234 13235 (prettify-symbols-end 13367 prettify-symbols-start 13366 composition (0 1 [32 65 57708]) fontified t) 13235 13236 (fontified t) 13236 13239 (face font-lock-builtin-face fontified t) 13239 13240 (fontified t) 13240 13241 (face font-lock-operator-face fontified t) 13241 13242 (fontified t) 13242 13246 (face font-lock-constant-face fontified t) 13246 13247 (fontified t) 13247 13248 (face font-lock-operator-face fontified t) 13248 13249 (fontified t) 13249 13253 (face font-lock-constant-face fontified t) 13253 13258 (fontified t) 13258 13260 (face font-lock-doc-face fontified t) 13260 13261 (face font-lock-doc-face syntax-table (15) fontified t) 13261 13308 (face font-lock-doc-face fontified t) 13308 13309 (face font-lock-doc-face syntax-table (15) fontified t) 13309 13311 (face font-lock-doc-face fontified t) 13311 13324 (fontified t) 13324 13325 (prettify-symbols-end 13457 prettify-symbols-start 13456 composition (0 1 [32 65 57708]) fontified t) 13325 13326 (fontified t) 13326 13329 (face font-lock-builtin-face fontified t) 13329 13330 (fontified t) 13330 13331 (face font-lock-operator-face fontified t) 13331 13332 (fontified t) 13332 13336 (face font-lock-constant-face fontified t) 13336 13337 (fontified t) 13337 13338 (face font-lock-operator-face fontified t) 13338 13339 (fontified t) 13339 13343 (face font-lock-constant-face fontified t) 13343 13348 (fontified t) 13348 13350 (face font-lock-doc-face fontified t) 13350 13351 (face font-lock-doc-face syntax-table (15) fontified t) 13351 13392 (face font-lock-doc-face fontified t) 13392 13393 (face font-lock-doc-face syntax-table (15) fontified t) 13393 13395 (face font-lock-doc-face fontified t) 13395 13404 (fontified t) 13404 13405 (prettify-symbols-end 13537 prettify-symbols-start 13536 composition (0 1 [32 65 57708]) fontified t) 13405 13406 (fontified t) 13406 13409 (face font-lock-builtin-face fontified t) 13409 13410 (fontified t) 13410 13411 (face font-lock-operator-face fontified t) 13411 13412 (fontified t) 13412 13416 (face font-lock-constant-face fontified t) 13416 13417 (fontified t) 13417 13418 (face font-lock-operator-face fontified t) 13418 13419 (fontified t) 13419 13423 (face font-lock-constant-face fontified t) 13423 13428 (fontified t) 13428 13430 (face font-lock-doc-face fontified t) 13430 13431 (face font-lock-doc-face syntax-table (15) fontified t) 13431 13641 (face font-lock-doc-face fontified t) 13641 13642 (face font-lock-doc-face syntax-table (15) fontified t) 13642 13644 (face font-lock-doc-face fontified t) 13644 13660 (fontified t) 13660 13661 (prettify-symbols-end 13793 prettify-symbols-start 13792 composition (0 1 [32 65 57708]) fontified t) 13661 13674 (fontified t) 13674 13675 (face font-lock-operator-face fontified t) 13675 13676 (fontified t) 13676 13680 (face font-lock-constant-face fontified t) 13680 13681 (fontified t) 13681 13682 (face font-lock-operator-face fontified t) 13682 13683 (fontified t) 13683 13687 (face font-lock-constant-face fontified t) 13687 13696 (fontified t) 13696 13697 (prettify-symbols-end 13829 prettify-symbols-start 13828 composition (0 1 [32 65 57708]) fontified t) 13697 13698 (fontified t) 13698 13702 (face font-lock-builtin-face fontified t) 13702 13703 (face (rainbow-delimiters-depth-1-face) fontified t) 13703 13706 (face font-lock-builtin-face fontified t) 13706 13711 (fontified t) 13711 13712 (face (rainbow-delimiters-depth-1-face) fontified t) 13712 13713 (fontified t) 13713 13714 (face font-lock-operator-face fontified t) 13714 13715 (fontified t) 13715 13719 (face font-lock-constant-face fontified t) 13719 13720 (fontified t) 13720 13721 (face font-lock-operator-face fontified t) 13721 13727 (fontified t) 13727 13728 (face (rainbow-delimiters-depth-1-face) fontified t) 13728 13733 (fontified t) 13733 13734 (face font-lock-operator-face fontified t) 13734 13741 (face font-lock-string-face fontified t) 13741 13750 (fontified t) 13750 13751 (face font-lock-operator-face fontified t) 13751 13755 (face font-lock-constant-face fontified t) 13755 13756 (face (rainbow-delimiters-depth-1-face) fontified t) 13756 13761 (fontified t) 13761 13763 (face font-lock-doc-face fontified t) 13763 13764 (face font-lock-doc-face syntax-table (15) fontified t) 13764 13991 (face font-lock-doc-face fontified t) 13991 13992 (face font-lock-doc-face syntax-table (15) fontified t) 13992 13994 (face font-lock-doc-face fontified t) 13994 13999 (fontified t) 13999 14011 (face font-lock-variable-name-face fontified t) 14011 14012 (fontified t) 14012 14013 (face font-lock-operator-face fontified t) 14013 14024 (fontified t) 14024 14025 (face (rainbow-delimiters-depth-1-face) fontified t) 14025 14030 (fontified t) 14030 14031 (face font-lock-operator-face fontified t) 14031 14038 (face font-lock-string-face fontified t) 14038 14039 (face (rainbow-delimiters-depth-1-face) fontified t) 14039 14045 (fontified t) 14045 14061 (face font-lock-type-face fontified t) 14061 14062 (face (rainbow-delimiters-depth-1-face) fontified t) 14062 14066 (fontified t) 14066 14067 (face font-lock-operator-face fontified t) 14067 14074 (face font-lock-string-face fontified t) 14074 14075 (face (rainbow-delimiters-depth-1-face) fontified t) 14075 14080 (fontified t) 14080 14083 (face font-lock-keyword-face fontified t) 14083 14084 (fontified t) 14084 14103 (face font-lock-function-name-face fontified t) 14103 14104 (face (rainbow-delimiters-depth-1-face) fontified t) 14104 14108 (face font-lock-keyword-face fontified t) 14108 14109 (face (rainbow-delimiters-depth-1-face) fontified t) 14109 14110 (fontified t) 14110 14111 (face font-lock-operator-face prettify-symbols-end 14244 prettify-symbols-start 14242 composition ((2 32 63 32 65 57620)) fontified t) 14111 14112 (face font-lock-operator-face prettify-symbols-end 14244 prettify-symbols-start 14242 composition ((2 32 63 32 65 57620)) fontified t) 14112 14113 (fontified t) 14113 14123 (face font-lock-string-face fontified t) 14123 14124 (prettify-symbols-end 14256 prettify-symbols-start 14255 composition ((1 32 65 57708)) fontified t) 14124 14133 (fontified t) 14133 14135 (face font-lock-doc-face fontified t) 14135 14136 (face font-lock-doc-face syntax-table (15) fontified t) 14136 14185 (face font-lock-doc-face fontified t) 14185 14186 (face font-lock-doc-face syntax-table (15) fontified t) 14186 14188 (face font-lock-doc-face fontified t) 14188 14197 (fontified t) 14197 14204 (face font-lock-variable-name-face fontified t) 14204 14205 (fontified t) 14205 14206 (face font-lock-operator-face fontified t) 14206 14207 (fontified t) 14207 14210 (face font-lock-builtin-face fontified t) 14210 14211 (face (rainbow-delimiters-depth-1-face) fontified t) 14211 14215 (face font-lock-keyword-face fontified t) 14215 14219 (fontified t) 14219 14220 (face (rainbow-delimiters-depth-1-face) fontified t) 14220 14229 (fontified t) 14229 14231 (face font-lock-keyword-face fontified t) 14231 14250 (fontified t) 14250 14251 (face (rainbow-delimiters-depth-1-face) fontified t) 14251 14252 (face (rainbow-delimiters-depth-2-face) fontified t) 14252 14261 (face font-lock-string-face fontified t) 14261 14263 (fontified t) 14263 14274 (face font-lock-string-face fontified t) 14274 14275 (face (rainbow-delimiters-depth-2-face) fontified t) 14275 14276 (face (rainbow-delimiters-depth-1-face) fontified t) 14276 14277 (prettify-symbols-end 14409 prettify-symbols-start 14408 composition ((1 32 65 57708)) fontified t) 14277 14290 (fontified t) 14290 14295 (face font-lock-keyword-face fontified t) 14295 14296 (fontified t) 14296 14306 (face font-lock-type-face fontified t) 14306 14307 (face (rainbow-delimiters-depth-1-face) fontified t) 14307 14308 (fontified t) 14308 14381 (face font-lock-string-face fontified t) 14381 14382 (face nil fontified t) 14382 14386 (face font-lock-keyword-face fontified t) 14386 14391 (face nil fontified t) 14391 14392 (face font-lock-string-face fontified t) 14392 14393 (face (rainbow-delimiters-depth-1-face) fontified t) 14393 14402 (fontified t) 14402 14408 (face font-lock-keyword-face fontified t) 14408 14409 (fontified t) 14409 14413 (face font-lock-keyword-face fontified t) 14413 14416 (fontified t) 14416 14421 (face font-lock-keyword-face fontified t) 14421 14422 (fontified t) 14422 14438 (face font-lock-type-face fontified t) 14438 14439 (face (rainbow-delimiters-depth-1-face) fontified t) 14439 14451 (fontified t) 14451 14452 (face (rainbow-delimiters-depth-1-face) fontified t) 14452 14453 (prettify-symbols-end 14585 prettify-symbols-start 14584 composition (0 1 [32 65 57708]) fontified t) 14453 14458 (fontified t) 14458 14460 (face font-lock-doc-face fontified t) 14460 14461 (face font-lock-doc-face syntax-table (15) fontified t) 14461 14522 (face font-lock-doc-face fontified t) 14522 14523 (face font-lock-doc-face syntax-table (15) fontified t) 14523 14525 (face font-lock-doc-face fontified t) 14525 14542 (fontified t) 14542 14543 (prettify-symbols-end 14675 prettify-symbols-start 14674 composition (0 1 [32 65 57708]) fontified t) 14543 14544 (fontified t) 14544 14547 (face font-lock-builtin-face fontified t) 14547 14552 (fontified t) 14552 14554 (face font-lock-string-face fontified t) 14554 14555 (face font-lock-string-face syntax-table (15) fontified t) 14555 14652 (face font-lock-string-face fontified t) 14652 14653 (face font-lock-string-face syntax-table (15) fontified t) 14653 14655 (face font-lock-string-face fontified t) 14655 14671 (fontified t) 14671 14672 (prettify-symbols-end 14804 prettify-symbols-start 14803 composition (0 1 [32 65 57708]) fontified t) 14672 14673 (fontified t) 14673 14676 (face font-lock-builtin-face fontified t) 14676 14677 (fontified t) 14677 14678 (face font-lock-operator-face fontified t) 14678 14679 (fontified t) 14679 14683 (face font-lock-constant-face fontified t) 14683 14684 (fontified t) 14684 14685 (face font-lock-operator-face fontified t) 14685 14686 (fontified t) 14686 14690 (face font-lock-constant-face fontified t) 14690 14695 (fontified t) 14695 14697 (face font-lock-doc-face fontified t) 14697 14698 (face font-lock-doc-face syntax-table (15) fontified t) 14698 14756 (face font-lock-doc-face fontified t) 14756 14757 (face font-lock-doc-face syntax-table (15) fontified t) 14757 14759 (face font-lock-doc-face fontified t) 14759 14772 (fontified t) 14772 14773 (prettify-symbols-end 14905 prettify-symbols-start 14904 composition (0 1 [32 65 57708]) fontified t) 14773 14774 (fontified t) 14774 14777 (face font-lock-builtin-face fontified t) 14777 14778 (fontified t) 14778 14779 (face font-lock-operator-face fontified t) 14779 14780 (fontified t) 14780 14784 (face font-lock-constant-face fontified t) 14784 14785 (fontified t) 14785 14786 (face font-lock-operator-face fontified t) 14786 14787 (fontified t) 14787 14791 (face font-lock-constant-face fontified t) 14791 14796 (fontified t) 14796 14798 (face font-lock-doc-face fontified t) 14798 14799 (face font-lock-doc-face syntax-table (15) fontified t) 14799 14959 (face font-lock-doc-face fontified t) 14959 14960 (face font-lock-doc-face syntax-table (15) fontified t) 14960 14962 (face font-lock-doc-face fontified t) 14962 14978 (fontified t) 14978 14979 (prettify-symbols-end 15111 prettify-symbols-start 15110 composition (0 1 [32 65 57708]) fontified t) 14979 14992 (fontified t) 14992 14993 (face font-lock-operator-face fontified t) 14993 14994 (fontified t) 14994 14998 (face font-lock-constant-face fontified t) 14998 14999 (fontified t) 14999 15000 (face font-lock-operator-face fontified t) 15000 15001 (fontified t) 15001 15005 (face font-lock-constant-face fontified t) 15005 15014 (fontified t) 15014 15015 (prettify-symbols-end 15147 prettify-symbols-start 15146 composition (0 1 [32 65 57708]) fontified t) 15015 15016 (fontified t) 15016 15020 (face font-lock-builtin-face fontified t) 15020 15021 (face (rainbow-delimiters-depth-1-face) fontified t) 15021 15024 (face font-lock-builtin-face fontified t) 15024 15029 (fontified t) 15029 15030 (face (rainbow-delimiters-depth-1-face) fontified t) 15030 15031 (fontified t) 15031 15032 (face font-lock-operator-face fontified t) 15032 15033 (fontified t) 15033 15037 (face font-lock-constant-face fontified t) 15037 15038 (fontified t) 15038 15039 (face font-lock-operator-face fontified t) 15039 15045 (fontified t) 15045 15046 (face (rainbow-delimiters-depth-1-face) fontified t) 15046 15051 (fontified t) 15051 15052 (face font-lock-operator-face fontified t) 15052 15059 (face font-lock-string-face fontified t) 15059 15068 (fontified t) 15068 15069 (face font-lock-operator-face fontified t) 15069 15073 (face font-lock-constant-face fontified t) 15073 15074 (face (rainbow-delimiters-depth-1-face) fontified t) 15074 15079 (fontified t) 15079 15081 (face font-lock-doc-face fontified t) 15081 15082 (face font-lock-doc-face syntax-table (15) fontified t) 15082 15309 (face font-lock-doc-face fontified t) 15309 15310 (face font-lock-doc-face syntax-table (15) fontified t) 15310 15312 (face font-lock-doc-face fontified t) 15312 15317 (fontified t) 15317 15329 (face font-lock-variable-name-face fontified t) 15329 15330 (fontified t) 15330 15331 (face font-lock-operator-face fontified t) 15331 15342 (fontified t) 15342 15343 (face (rainbow-delimiters-depth-1-face) fontified t) 15343 15348 (fontified t) 15348 15349 (face font-lock-operator-face fontified t) 15349 15356 (face font-lock-string-face fontified t) 15356 15357 (face (rainbow-delimiters-depth-1-face) fontified t) 15357 15360 (fontified t) 15360 15365 (face font-lock-keyword-face fontified t) 15365 15366 (fontified t) 15366 15385 (face font-lock-type-face fontified t) 15385 15386 (face (rainbow-delimiters-depth-1-face) fontified t) 15386 15396 (fontified t) 15396 15397 (face (rainbow-delimiters-depth-1-face) fontified t) 15397 15398 (prettify-symbols-end 15530 prettify-symbols-start 15529 composition (0 1 [32 65 57708]) fontified t) 15398 15403 (fontified t) 15403 15405 (face font-lock-doc-face fontified t) 15405 15406 (face font-lock-doc-face syntax-table (15) fontified t) 15406 15472 (face font-lock-doc-face fontified t) 15472 15473 (face font-lock-doc-face syntax-table (15) fontified t) 15473 15475 (face font-lock-doc-face fontified t) 15475 15490 (fontified t) 15490 15491 (prettify-symbols-end 15623 prettify-symbols-start 15622 composition (0 1 [32 65 57708]) fontified t) 15491 15492 (fontified t) 15492 15496 (face font-lock-builtin-face fontified t) 15496 15497 (face (rainbow-delimiters-depth-1-face) fontified t) 15497 15505 (fontified t) 15505 15506 (face (rainbow-delimiters-depth-1-face) fontified t) 15506 15509 (fontified t) 15509 15514 (face font-lock-keyword-face fontified t) 15514 15515 (fontified t) 15515 15543 (face font-lock-type-face fontified t) 15543 15544 (face (rainbow-delimiters-depth-1-face) fontified t) 15544 15555 (fontified t) 15555 15556 (face (rainbow-delimiters-depth-2-face) fontified t) 15556 15563 (fontified t) 15563 15564 (face (rainbow-delimiters-depth-3-face) fontified t) 15564 15590 (face font-lock-string-face fontified t) 15590 15591 (face (rainbow-delimiters-depth-3-face) fontified t) 15591 15592 (face (rainbow-delimiters-depth-2-face) fontified t) 15592 15593 (face (rainbow-delimiters-depth-1-face) fontified t) 15593 15594 (prettify-symbols-end 15726 prettify-symbols-start 15725 composition (0 1 [32 65 57708]) fontified t) 15594 15599 (fontified t) 15599 15601 (face font-lock-doc-face fontified t) 15601 15602 (face font-lock-doc-face syntax-table (15) fontified t) 15602 15678 (face font-lock-doc-face fontified t) 15678 15679 (face font-lock-doc-face syntax-table (15) fontified t) 15679 15681 (face font-lock-doc-face fontified t) 15681 15693 (fontified t) 15693 15694 (prettify-symbols-end 15826 prettify-symbols-start 15825 composition (0 1 [32 65 57708]) fontified t) 15694 15702 (fontified t) 15702 15703 (face (rainbow-delimiters-depth-1-face) fontified t) 15703 15729 (face font-lock-string-face fontified t) 15729 15730 (face (rainbow-delimiters-depth-1-face) fontified t) 15730 15733 (fontified t) 15733 15738 (face font-lock-keyword-face fontified t) 15738 15739 (fontified t) 15739 15766 (face font-lock-type-face fontified t) 15766 15767 (face (rainbow-delimiters-depth-1-face) fontified t) 15767 15777 (fontified t) 15777 15778 (face (rainbow-delimiters-depth-1-face) fontified t) 15778 15779 (prettify-symbols-end 15911 prettify-symbols-start 15910 composition (0 1 [32 65 57708]) fontified t) 15779 15784 (fontified t) 15784 15786 (face font-lock-doc-face fontified t) 15786 15787 (face font-lock-doc-face syntax-table (15) fontified t) 15787 15863 (face font-lock-doc-face fontified t) 15863 15864 (face font-lock-doc-face syntax-table (15) fontified t) 15864 15866 (face font-lock-doc-face fontified t) 15866 15889 (fontified t) 15889 15890 (prettify-symbols-end 16022 prettify-symbols-start 16021 composition (0 1 [32 65 57708]) fontified t) 15890 15891 (fontified t) 15891 15895 (face font-lock-builtin-face fontified t) 15895 15896 (face (rainbow-delimiters-depth-1-face) fontified t) 15896 15912 (fontified t) 15912 15913 (face (rainbow-delimiters-depth-1-face) fontified t) 15913 15916 (fontified t) 15916 15921 (face font-lock-keyword-face fontified t) 15921 15922 (fontified t) 15922 15947 (face font-lock-type-face fontified t) 15947 15948 (face (rainbow-delimiters-depth-1-face) fontified t) 15948 15961 (fontified t) 15961 15962 (face (rainbow-delimiters-depth-1-face) fontified t) 15962 15963 (prettify-symbols-end 16095 prettify-symbols-start 16094 composition (0 1 [32 65 57708]) fontified t) 15963 15968 (fontified t) 15968 15970 (face font-lock-doc-face fontified t) 15970 15971 (face font-lock-doc-face syntax-table (15) fontified t) 15971 16005 (face font-lock-doc-face fontified t) 16005 16006 (face font-lock-doc-face syntax-table (15) fontified t) 16006 16008 (face font-lock-doc-face fontified t) 16008 16017 (fontified t) 16017 16018 (prettify-symbols-end 16150 prettify-symbols-start 16149 composition (0 1 [32 65 57708]) fontified t) 16018 16028 (fontified t) 16028 16029 (face (rainbow-delimiters-depth-1-face) fontified t) 16029 16051 (fontified t) 16051 16052 (face (rainbow-delimiters-depth-2-face) fontified t) 16052 16065 (fontified t) 16065 16066 (face font-lock-operator-face fontified t) 16066 16071 (face font-lock-constant-face fontified t) 16071 16072 (face (rainbow-delimiters-depth-2-face) fontified t) 16072 16073 (face (rainbow-delimiters-depth-1-face) fontified t) 16073 16078 (fontified t) 16078 16080 (face font-lock-string-face fontified t) 16080 16081 (face font-lock-string-face syntax-table (15) fontified t) 16081 16201 (face font-lock-string-face fontified t) 16201 16202 (face font-lock-string-face syntax-table (15) fontified t) 16202 16204 (face font-lock-string-face fontified t) 16204 16209 (fontified t) 16209 16221 (face font-lock-variable-name-face fontified t) 16221 16222 (fontified t) 16222 16223 (face font-lock-operator-face fontified t) 16223 16234 (fontified t) 16234 16235 (face (rainbow-delimiters-depth-1-face) fontified t) 16235 16240 (fontified t) 16240 16241 (face font-lock-operator-face fontified t) 16241 16248 (face font-lock-string-face fontified t) 16248 16249 (face (rainbow-delimiters-depth-1-face) fontified t) 16249 16252 (fontified t) 16252 16257 (face font-lock-keyword-face fontified t) 16257 16258 (fontified t) 16258 16277 (face font-lock-type-face fontified t) 16277 16278 (face (rainbow-delimiters-depth-1-face) fontified t) 16278 16285 (fontified t) 16285 16286 (face (rainbow-delimiters-depth-2-face) fontified t) 16286 16320 (fontified t) 16320 16321 (face (rainbow-delimiters-depth-3-face) fontified t) 16321 16337 (face font-lock-string-face fontified t) 16337 16338 (face (rainbow-delimiters-depth-3-face) fontified t) 16338 16339 (face (rainbow-delimiters-depth-2-face) fontified t) 16339 16340 (face (rainbow-delimiters-depth-1-face) fontified t) 16340 16341 (prettify-symbols-end 16473 prettify-symbols-start 16472 composition (0 1 [32 65 57708]) fontified t) 16341 16346 (fontified t) 16346 16348 (face font-lock-doc-face fontified t) 16348 16349 (face font-lock-doc-face syntax-table (15) fontified t) 16349 16417 (face font-lock-doc-face fontified t) 16417 16418 (face font-lock-doc-face syntax-table (15) fontified t) 16418 16420 (face font-lock-doc-face fontified t) 16420 16432 (fontified t) 16432 16433 (prettify-symbols-end 16565 prettify-symbols-start 16564 composition (0 1 [32 65 57708]) fontified t) 16433 16441 (fontified t) 16441 16442 (face (rainbow-delimiters-depth-1-face) fontified t) 16442 16458 (face font-lock-string-face fontified t) 16458 16459 (face (rainbow-delimiters-depth-1-face) fontified t) 16459 16470 (fontified t) 16470 16471 (prettify-symbols-end 16603 prettify-symbols-start 16602 composition (0 1 [32 65 57708]) fontified t) 16471 16500 (fontified t) 16500 16505 (face font-lock-keyword-face fontified t) 16505 16506 (fontified t) 16506 16522 (face font-lock-type-face fontified t) 16522 16523 (face (rainbow-delimiters-depth-1-face) fontified t) 16523 16532 (fontified t) 16532 16533 (face (rainbow-delimiters-depth-1-face) fontified t) 16533 16534 (prettify-symbols-end 16666 prettify-symbols-start 16665 composition (0 1 [32 65 57708]) fontified t) 16534 16539 (fontified t) 16539 16541 (face font-lock-doc-face fontified t) 16541 16542 (face font-lock-doc-face syntax-table (15) fontified t) 16542 16594 (face font-lock-doc-face fontified t) 16594 16595 (face font-lock-doc-face syntax-table (15) fontified t) 16595 16597 (face font-lock-doc-face fontified t) 16597 16606 (fontified t) 16606 16607 (prettify-symbols-end 16739 prettify-symbols-start 16738 composition ((1 32 65 57708)) fontified t) 16607 16617 (fontified t) 16617 16618 (face (rainbow-delimiters-depth-1-face) fontified t) 16618 16640 (fontified t) 16640 16641 (face (rainbow-delimiters-depth-2-face) fontified t) 16641 16654 (fontified t) 16654 16655 (face font-lock-operator-face fontified t) 16655 16660 (face font-lock-constant-face fontified t) 16660 16661 (face (rainbow-delimiters-depth-2-face) fontified t) 16661 16662 (face (rainbow-delimiters-depth-1-face) fontified t) 16662 16667 (fontified t) 16667 16669 (face font-lock-string-face fontified t) 16669 16670 (face font-lock-string-face syntax-table (15) fontified t) 16670 16695 (face font-lock-string-face fontified t) 16695 16696 (face font-lock-string-face syntax-table (15) fontified t) 16696 16698 (face font-lock-string-face fontified t) 16698 16711 (fontified t) 16711 16712 (prettify-symbols-end 16844 prettify-symbols-start 16843 composition ((1 32 65 57708)) fontified t) 16712 16713 (fontified t) 16713 16716 (face font-lock-builtin-face fontified t) 16716 16717 (fontified t) 16717 16718 (face font-lock-operator-face fontified t) 16718 16719 (fontified t) 16719 16723 (face font-lock-constant-face fontified t) 16723 16724 (fontified t) 16724 16725 (face font-lock-operator-face fontified t) 16725 16726 (fontified t) 16726 16730 (face font-lock-constant-face fontified t) 16730 16735 (fontified t) 16735 16737 (face font-lock-doc-face fontified t) 16737 16738 (face font-lock-doc-face syntax-table (15) fontified t) 16738 16779 (face font-lock-doc-face fontified t) 16779 16780 (face font-lock-doc-face syntax-table (15) fontified t) 16780 16782 (face font-lock-doc-face fontified t) 16782 16791 (fontified t) 16791 16792 (prettify-symbols-end 16924 prettify-symbols-start 16923 composition ((1 32 65 57708)) fontified t) 16792 16793 (fontified t) 16793 16797 (face font-lock-builtin-face fontified t) 16797 16798 (face (rainbow-delimiters-depth-1-face) fontified t) 16798 16801 (face font-lock-builtin-face fontified t) 16801 16806 (fontified t) 16806 16807 (face (rainbow-delimiters-depth-1-face) fontified t) 16807 16808 (fontified t) 16808 16809 (face font-lock-operator-face fontified t) 16809 16810 (fontified t) 16810 16814 (face font-lock-constant-face fontified t) 16814 16815 (fontified t) 16815 16816 (face font-lock-operator-face fontified t) 16816 16822 (fontified t) 16822 16823 (face (rainbow-delimiters-depth-1-face) fontified t) 16823 16828 (fontified t) 16828 16829 (face font-lock-operator-face fontified t) 16829 16836 (face font-lock-string-face fontified t) 16836 16845 (fontified t) 16845 16846 (face font-lock-operator-face fontified t) 16846 16850 (face font-lock-constant-face fontified t) 16850 16851 (face (rainbow-delimiters-depth-1-face) fontified t) 16851 16856 (fontified t) 16856 16858 (face font-lock-doc-face fontified t) 16858 16859 (face font-lock-doc-face syntax-table (15) fontified t) 16859 17086 (face font-lock-doc-face fontified t) 17086 17087 (face font-lock-doc-face syntax-table (15) fontified t) 17087 17089 (face font-lock-doc-face fontified t) 17089 17094 (fontified t) 17094 17106 (face font-lock-variable-name-face fontified t) 17106 17107 (fontified t) 17107 17108 (face font-lock-operator-face fontified t) 17108 17119 (fontified t) 17119 17120 (face (rainbow-delimiters-depth-1-face) fontified t) 17120 17125 (fontified t) 17125 17126 (face font-lock-operator-face fontified t) 17126 17133 (face font-lock-string-face fontified t) 17133 17134 (face (rainbow-delimiters-depth-1-face) fontified t) 17134 17137 (fontified t) 17137 17142 (face font-lock-keyword-face fontified t) 17142 17143 (fontified t) 17143 17163 (face font-lock-type-face fontified t) 17163 17164 (face (rainbow-delimiters-depth-1-face) fontified t) 17164 17180 (fontified t) 17180 17181 (face (rainbow-delimiters-depth-1-face) fontified t) 17181 17182 (prettify-symbols-end 17314 prettify-symbols-start 17313 composition ((1 32 65 57708)) fontified t) 17182 17187 (fontified t) 17187 17189 (face font-lock-doc-face fontified t) 17189 17190 (face font-lock-doc-face syntax-table (15) fontified t) 17190 17218 (face font-lock-doc-face fontified t) 17218 17219 (face font-lock-doc-face syntax-table (15) fontified t) 17219 17221 (face font-lock-doc-face fontified t) 17221 17231 (fontified t) 17231 17232 (prettify-symbols-end 17364 prettify-symbols-start 17363 composition ((1 32 65 57708)) fontified t) 17232 17233 (fontified t) 17233 17236 (face font-lock-builtin-face fontified t) 17236 17241 (fontified t) 17241 17243 (face font-lock-string-face fontified t) 17243 17244 (face font-lock-string-face syntax-table (15) fontified t) 17244 17368 (face font-lock-string-face fontified t) 17368 17369 (face font-lock-string-face syntax-table (15) fontified t) 17369 17371 (face font-lock-string-face fontified t) 17371 17374 (fontified t) 17374 17379 (face font-lock-keyword-face fontified t) 17379 17380 (fontified t) 17380 17400 (face font-lock-type-face fontified t) 17400 17401 (face (rainbow-delimiters-depth-1-face) fontified t) 17401 17417 (fontified t) 17417 17418 (face (rainbow-delimiters-depth-1-face) fontified t) 17418 17419 (prettify-symbols-end 17551 prettify-symbols-start 17550 composition (0 1 [32 65 57708]) fontified t) 17419 17424 (fontified t) 17424 17426 (face font-lock-doc-face fontified t) 17426 17427 (face font-lock-doc-face syntax-table (15) fontified t) 17427 17457 (face font-lock-doc-face fontified t) 17457 17458 (face font-lock-doc-face syntax-table (15) fontified t) 17458 17460 (face font-lock-doc-face fontified t) 17460 17470 (fontified t) 17470 17471 (prettify-symbols-end 17603 prettify-symbols-start 17602 composition (0 1 [32 65 57708]) fontified t) 17471 17472 (fontified t) 17472 17475 (face font-lock-builtin-face fontified t) 17475 17480 (fontified t) 17480 17482 (face font-lock-string-face fontified t) 17482 17483 (face font-lock-string-face syntax-table (15) fontified t) 17483 17548 (face font-lock-string-face fontified t) 17548 17549 (face font-lock-string-face syntax-table (15) fontified t) 17549 17551 (face font-lock-string-face fontified t) 17551 17554 (fontified t) 17554 17559 (face font-lock-keyword-face fontified t) 17559 17560 (fontified t) 17560 17578 (face font-lock-type-face fontified t) 17578 17579 (face (rainbow-delimiters-depth-1-face) fontified t) 17579 17585 (fontified t) 17585 17586 (face (rainbow-delimiters-depth-1-face) fontified t) 17586 17587 (prettify-symbols-end 17719 prettify-symbols-start 17718 composition (0 1 [32 65 57708]) fontified t) 17587 17592 (fontified t) 17592 17594 (face font-lock-doc-face fontified t) 17594 17595 (face font-lock-doc-face syntax-table (15) fontified t) 17595 17661 (face font-lock-doc-face fontified t) 17661 17662 (face font-lock-doc-face syntax-table (15) fontified t) 17662 17664 (face font-lock-doc-face fontified t) 17664 17678 (fontified t) 17678 17679 (prettify-symbols-end 17811 prettify-symbols-start 17810 composition (0 1 [32 65 57708]) fontified t) 17679 17680 (fontified t) 17680 17684 (face font-lock-builtin-face fontified t) 17684 17685 (face (rainbow-delimiters-depth-1-face) fontified t) 17685 17706 (fontified t) 17706 17707 (face font-lock-operator-face fontified t) 17707 17728 (fontified t) 17728 17729 (face (rainbow-delimiters-depth-1-face) fontified t) 17729 17732 (fontified t) 17732 17737 (face font-lock-keyword-face fontified t) 17737 17738 (fontified t) 17738 17769 (face font-lock-type-face fontified t) 17769 17770 (face (rainbow-delimiters-depth-1-face) fontified t) 17770 17787 (fontified t) 17787 17788 (face (rainbow-delimiters-depth-2-face) fontified t) 17788 17807 (fontified t) 17807 17808 (face font-lock-operator-face fontified t) 17808 17809 (fontified t) 17809 17813 (face font-lock-constant-face fontified t) 17813 17822 (fontified t) 17822 17823 (face (rainbow-delimiters-depth-3-face) fontified t) 17823 17861 (face font-lock-string-face fontified t) 17861 17862 (face (rainbow-delimiters-depth-3-face) fontified t) 17862 17863 (face (rainbow-delimiters-depth-2-face) fontified t) 17863 17864 (fontified t) 17864 17865 (face (rainbow-delimiters-depth-1-face) fontified t) 17865 17866 (prettify-symbols-end 17998 prettify-symbols-start 17997 composition (0 1 [32 65 57708]) fontified t) 17866 17871 (fontified t) 17871 17873 (face font-lock-doc-face fontified t) 17873 17874 (face font-lock-doc-face syntax-table (15) fontified t) 17874 18013 (face font-lock-doc-face fontified t) 18013 18014 (face font-lock-doc-face syntax-table (15) fontified t) 18014 18016 (face font-lock-doc-face fontified t) 18016 18028 (fontified t) 18028 18029 (prettify-symbols-end 18161 prettify-symbols-start 18160 composition (0 1 [32 65 57708]) fontified t) 18029 18037 (fontified t) 18037 18038 (face (rainbow-delimiters-depth-1-face) fontified t) 18038 18076 (face font-lock-string-face fontified t) 18076 18077 (face (rainbow-delimiters-depth-1-face) fontified t) 18077 18088 (fontified t) 18088 18089 (prettify-symbols-end 18221 prettify-symbols-start 18220 composition (0 1 [32 65 57708]) fontified t) 18089 18109 (fontified t) 18109 18110 (face font-lock-operator-face fontified t) 18110 18111 (fontified t) 18111 18115 (face font-lock-constant-face fontified t) 18115 18116 (fontified t) 18116 18117 (face font-lock-operator-face fontified t) 18117 18118 (fontified t) 18118 18122 (face font-lock-constant-face fontified t) 18122 18125 (fontified t) 18125 18130 (face font-lock-keyword-face fontified t) 18130 18131 (fontified t) 18131 18153 (face font-lock-type-face fontified t) 18153 18154 (face (rainbow-delimiters-depth-1-face) fontified t) 18154 18167 (fontified t) 18167 18168 (face (rainbow-delimiters-depth-1-face) fontified t) 18168 18169 (prettify-symbols-end 18301 prettify-symbols-start 18300 composition (0 1 [32 65 57708]) fontified t) 18169 18174 (fontified t) 18174 18176 (face font-lock-doc-face fontified t) 18176 18177 (face font-lock-doc-face syntax-table (15) fontified t) 18177 18218 (face font-lock-doc-face fontified t) 18218 18219 (face font-lock-doc-face syntax-table (15) fontified t) 18219 18221 (face font-lock-doc-face fontified t) 18221 18230 (fontified t) 18230 18231 (prettify-symbols-end 18363 prettify-symbols-start 18362 composition (0 1 [32 65 57708]) fontified t) 18231 18241 (fontified t) 18241 18242 (face (rainbow-delimiters-depth-1-face) fontified t) 18242 18264 (fontified t) 18264 18265 (face (rainbow-delimiters-depth-2-face) fontified t) 18265 18278 (fontified t) 18278 18279 (face font-lock-operator-face fontified t) 18279 18284 (face font-lock-constant-face fontified t) 18284 18285 (face (rainbow-delimiters-depth-2-face) fontified t) 18285 18286 (face (rainbow-delimiters-depth-1-face) fontified t) 18286 18291 (fontified t) 18291 18293 (face font-lock-string-face fontified t) 18293 18294 (face font-lock-string-face syntax-table (15) fontified t) 18294 18422 (face font-lock-string-face fontified t) 18422 18423 (face font-lock-string-face syntax-table (15) fontified t) 18423 18425 (face font-lock-string-face fontified t) 18425 18430 (fontified t) 18430 18442 (face font-lock-variable-name-face fontified t) 18442 18443 (fontified t) 18443 18444 (face font-lock-operator-face fontified t) 18444 18455 (fontified t) 18455 18456 (face (rainbow-delimiters-depth-1-face) fontified t) 18456 18461 (fontified t) 18461 18462 (face font-lock-operator-face fontified t) 18462 18469 (face font-lock-string-face fontified t) 18469 18470 (face (rainbow-delimiters-depth-1-face) fontified t) 18470 18473 (fontified t) 18473 18478 (face font-lock-keyword-face fontified t) 18478 18479 (fontified t) 18479 18495 (face font-lock-type-face fontified t) 18495 18496 (face (rainbow-delimiters-depth-1-face) fontified t) 18496 18503 (fontified t) 18503 18504 (face (rainbow-delimiters-depth-2-face) fontified t) 18504 18535 (fontified t) 18535 18536 (face (rainbow-delimiters-depth-3-face) fontified t) 18536 18557 (face font-lock-string-face fontified t) 18557 18558 (face (rainbow-delimiters-depth-3-face) fontified t) 18558 18559 (face (rainbow-delimiters-depth-2-face) fontified t) 18559 18560 (face (rainbow-delimiters-depth-1-face) fontified t) 18560 18561 (prettify-symbols-end 18693 prettify-symbols-start 18692 composition (0 1 [32 65 57708]) fontified t) 18561 18566 (fontified t) 18566 18568 (face font-lock-doc-face fontified t) 18568 18569 (face font-lock-doc-face syntax-table (15) fontified t) 18569 18702 (face font-lock-doc-face fontified t) 18702 18703 (face font-lock-doc-face syntax-table (15) fontified t) 18703 18705 (face font-lock-doc-face fontified t) 18705 18717 (fontified t) 18717 18718 (prettify-symbols-end 18850 prettify-symbols-start 18849 composition (0 1 [32 65 57708]) fontified t) 18718 18726 (fontified t) 18726 18727 (face (rainbow-delimiters-depth-1-face) fontified t) 18727 18748 (face font-lock-string-face fontified t) 18748 18749 (face (rainbow-delimiters-depth-1-face) fontified t) 18749 18760 (fontified t) 18760 18761 (prettify-symbols-end 18893 prettify-symbols-start 18892 composition (0 1 [32 65 57708]) fontified t) 18761 18787 (fontified t) 18787 18792 (face font-lock-keyword-face fontified t) 18792 18793 (fontified t) 18793 18817 (face font-lock-type-face fontified t) 18817 18818 (face (rainbow-delimiters-depth-1-face) fontified t) 18818 18831 (fontified t) 18831 18832 (face (rainbow-delimiters-depth-1-face) fontified t) 18832 18833 (prettify-symbols-end 18965 prettify-symbols-start 18964 composition (0 1 [32 65 57708]) fontified t) 18833 18838 (fontified t) 18838 18840 (face font-lock-doc-face fontified t) 18840 18841 (face font-lock-doc-face syntax-table (15) fontified t) 18841 18886 (face font-lock-doc-face fontified t) 18886 18887 (face font-lock-doc-face syntax-table (15) fontified t) 18887 18889 (face font-lock-doc-face fontified t) 18889 18898 (fontified t) 18898 18899 (prettify-symbols-end 19031 prettify-symbols-start 19030 composition (0 1 [32 65 57708]) fontified t) 18899 18909 (fontified t) 18909 18910 (face (rainbow-delimiters-depth-1-face) fontified t) 18910 18932 (fontified t) 18932 18933 (face (rainbow-delimiters-depth-2-face) fontified t) 18933 18946 (fontified t) 18946 18947 (face font-lock-operator-face fontified t) 18947 18952 (face font-lock-constant-face fontified t) 18952 18953 (face (rainbow-delimiters-depth-2-face) fontified t) 18953 18954 (face (rainbow-delimiters-depth-1-face) fontified t) 18954 18959 (fontified t) 18959 18961 (face font-lock-string-face fontified t) 18961 18962 (face font-lock-string-face syntax-table (15) fontified t) 18962 19006 (face font-lock-string-face fontified t) 19006 19007 (face font-lock-string-face syntax-table (15) fontified t) 19007 19009 (face font-lock-string-face fontified t) 19009 19014 (fontified t) 19014 19026 (face font-lock-variable-name-face fontified t) 19026 19027 (fontified t) 19027 19028 (face font-lock-operator-face fontified t) 19028 19039 (fontified t) 19039 19040 (face (rainbow-delimiters-depth-1-face) fontified t) 19040 19045 (fontified t) 19045 19046 (face font-lock-operator-face fontified t) 19046 19053 (face font-lock-string-face fontified t) 19053 19054 (face (rainbow-delimiters-depth-1-face) fontified t) 19054 19057 (fontified t) 19057 19062 (face font-lock-keyword-face fontified t) 19062 19063 (fontified t) 19063 19081 (face font-lock-type-face fontified t) 19081 19082 (face (rainbow-delimiters-depth-1-face) fontified t) 19082 19089 (fontified t) 19089 19090 (face (rainbow-delimiters-depth-2-face) fontified t) 19090 19123 (fontified t) 19123 19124 (face (rainbow-delimiters-depth-3-face) fontified t) 19124 19147 (face font-lock-string-face fontified t) 19147 19148 (face (rainbow-delimiters-depth-3-face) fontified t) 19148 19149 (face (rainbow-delimiters-depth-2-face) fontified t) 19149 19150 (face (rainbow-delimiters-depth-1-face) fontified t) 19150 19151 (prettify-symbols-end 19283 prettify-symbols-start 19282 composition (0 1 [32 65 57708]) fontified t) 19151 19156 (fontified t) 19156 19158 (face font-lock-doc-face fontified t) 19158 19159 (face font-lock-doc-face syntax-table (15) fontified t) 19159 19269 (face font-lock-doc-face fontified t) 19269 19270 (face font-lock-doc-face syntax-table (15) fontified t) 19270 19272 (face font-lock-doc-face fontified t) 19272 19284 (fontified t) 19284 19285 (prettify-symbols-end 19417 prettify-symbols-start 19416 composition (0 1 [32 65 57708]) fontified t) 19285 19293 (fontified t) 19293 19294 (face (rainbow-delimiters-depth-1-face) fontified t) 19294 19317 (face font-lock-string-face fontified t) 19317 19318 (face (rainbow-delimiters-depth-1-face) fontified t) 19318 19329 (fontified t) 19329 19330 (prettify-symbols-end 19462 prettify-symbols-start 19461 composition (0 1 [32 65 57708]) fontified t) 19330 19358 (fontified t) 19358 19363 (face font-lock-keyword-face fontified t) 19363 19364 (fontified t) 19364 19397 (face font-lock-type-face fontified t) 19397 19398 (face (rainbow-delimiters-depth-1-face) fontified t) 19398 19416 (fontified t) 19416 19417 (face (rainbow-delimiters-depth-1-face) fontified t) 19417 19418 (prettify-symbols-end 19550 prettify-symbols-start 19549 composition (0 1 [32 65 57708]) fontified t) 19418 19423 (fontified t) 19423 19425 (face font-lock-doc-face fontified t) 19425 19426 (face font-lock-doc-face syntax-table (15) fontified t) 19426 19471 (face font-lock-doc-face fontified t) 19471 19472 (face font-lock-doc-face syntax-table (15) fontified t) 19472 19474 (face font-lock-doc-face fontified t) 19474 19483 (fontified t) 19483 19484 (prettify-symbols-end 19616 prettify-symbols-start 19615 composition (0 1 [32 65 57708]) fontified t) 19484 19494 (fontified t) 19494 19495 (face (rainbow-delimiters-depth-1-face) fontified t) 19495 19517 (fontified t) 19517 19518 (face (rainbow-delimiters-depth-2-face) fontified t) 19518 19531 (fontified t) 19531 19532 (face font-lock-operator-face fontified t) 19532 19537 (face font-lock-constant-face fontified t) 19537 19538 (face (rainbow-delimiters-depth-2-face) fontified t) 19538 19539 (face (rainbow-delimiters-depth-1-face) fontified t) 19539 19544 (fontified t) 19544 19546 (face font-lock-string-face fontified t) 19546 19547 (face font-lock-string-face syntax-table (15) fontified t) 19547 19687 (face font-lock-string-face fontified t) 19687 19688 (face font-lock-string-face syntax-table (15) fontified t) 19688 19690 (face font-lock-string-face fontified t) 19690 19695 (fontified t) 19695 19707 (face font-lock-variable-name-face fontified t) 19707 19708 (fontified t) 19708 19709 (face font-lock-operator-face fontified t) 19709 19720 (fontified t) 19720 19721 (face (rainbow-delimiters-depth-1-face) fontified t) 19721 19726 (fontified t) 19726 19727 (face font-lock-operator-face fontified t) 19727 19734 (face font-lock-string-face fontified t) 19734 19735 (face (rainbow-delimiters-depth-1-face) fontified t) 19735 19738 (fontified t) 19738 19743 (face font-lock-keyword-face fontified t) 19743 19744 (fontified t) 19744 19771 (face font-lock-type-face fontified t) 19771 19772 (face (rainbow-delimiters-depth-1-face) fontified t) 19772 19789 (fontified t) 19789 19790 (face (rainbow-delimiters-depth-2-face) fontified t) 19790 19832 (fontified t) 19832 19833 (face (rainbow-delimiters-depth-3-face) fontified t) 19833 19866 (face font-lock-string-face fontified t) 19866 19867 (face (rainbow-delimiters-depth-3-face) fontified t) 19867 19868 (face (rainbow-delimiters-depth-2-face) fontified t) 19868 19869 (fontified t) 19869 19870 (face (rainbow-delimiters-depth-1-face) fontified t) 19870 19871 (prettify-symbols-end 20003 prettify-symbols-start 20002 composition (0 1 [32 65 57708]) fontified t) 19871 19876 (fontified t) 19876 19878 (face font-lock-doc-face fontified t) 19878 19879 (face font-lock-doc-face syntax-table (15) fontified t) 19879 20010 (face font-lock-doc-face fontified t) 20010 20011 (face font-lock-doc-face syntax-table (15) fontified t) 20011 20013 (face font-lock-doc-face fontified t) 20013 20025 (fontified t) 20025 20026 (prettify-symbols-end 20158 prettify-symbols-start 20157 composition (0 1 [32 65 57708]) fontified t) 20026 20034 (fontified t) 20034 20035 (face (rainbow-delimiters-depth-1-face) fontified t) 20035 20068 (face font-lock-string-face fontified t) 20068 20069 (face (rainbow-delimiters-depth-1-face) fontified t) 20069 20080 (fontified t) 20080 20081 (prettify-symbols-end 20213 prettify-symbols-start 20212 composition (0 1 [32 65 57708]) fontified t) 20081 20118 (fontified t) 20118 20123 (face font-lock-keyword-face fontified t) 20123 20124 (fontified t) 20124 20142 (face font-lock-type-face fontified t) 20142 20143 (face (rainbow-delimiters-depth-1-face) fontified t) 20143 20154 (fontified t) 20154 20155 (face (rainbow-delimiters-depth-2-face) fontified t) 20155 20162 (fontified t) 20162 20163 (face (rainbow-delimiters-depth-3-face) fontified t) 20163 20177 (face font-lock-string-face fontified t) 20177 20178 (face (rainbow-delimiters-depth-3-face) fontified t) 20178 20179 (face (rainbow-delimiters-depth-2-face) fontified t) 20179 20180 (face (rainbow-delimiters-depth-1-face) fontified t) 20180 20181 (prettify-symbols-end 20313 prettify-symbols-start 20312 composition (0 1 [32 65 57708]) fontified t) 20181 20186 (fontified t) 20186 20188 (face font-lock-doc-face fontified t) 20188 20189 (face font-lock-doc-face syntax-table (15) fontified t) 20189 20260 (face font-lock-doc-face fontified t) 20260 20261 (face font-lock-doc-face syntax-table (15) fontified t) 20261 20263 (face font-lock-doc-face fontified t) 20263 20275 (fontified t) 20275 20276 (prettify-symbols-end 20408 prettify-symbols-start 20407 composition (0 1 [32 65 57708]) fontified t) 20276 20284 (fontified t) 20284 20285 (face (rainbow-delimiters-depth-1-face) fontified t) 20285 20299 (face font-lock-string-face fontified t) 20299 20300 (face (rainbow-delimiters-depth-1-face) fontified t) 20300 20303 (fontified t) 20303 20308 (face font-lock-keyword-face fontified t) 20308 20309 (fontified t) 20309 20323 (face font-lock-type-face fontified t) 20323 20324 (face (rainbow-delimiters-depth-1-face) fontified t) 20324 20333 (fontified t) 20333 20334 (face (rainbow-delimiters-depth-1-face) fontified t) 20334 20335 (prettify-symbols-end 20467 prettify-symbols-start 20466 composition ((1 32 65 57708)) fontified t) 20335 20340 (fontified t) 20340 20342 (face font-lock-doc-face fontified t) 20342 20343 (face font-lock-doc-face syntax-table (15) fontified t) 20343 20377 (face font-lock-doc-face fontified t) 20377 20378 (face font-lock-doc-face syntax-table (15) fontified t) 20378 20380 (face font-lock-doc-face fontified t) 20380 20390 (fontified t) 20390 20391 (prettify-symbols-end 20523 prettify-symbols-start 20522 composition ((1 32 65 57708)) fontified t) 20391 20392 (fontified t) 20392 20395 (face font-lock-builtin-face fontified t) 20395 20400 (fontified t) 20400 20402 (face font-lock-string-face fontified t) 20402 20403 (face font-lock-string-face syntax-table (15) fontified t) 20403 20428 (face font-lock-string-face fontified t) 20428 20429 (face font-lock-string-face syntax-table (15) fontified t) 20429 20431 (face font-lock-string-face fontified t) 20431 20447 (fontified t) 20447 20448 (prettify-symbols-end 20580 prettify-symbols-start 20579 composition (0 1 [32 65 57708]) fontified t) 20448 20449 (fontified t) 20449 20452 (face font-lock-builtin-face fontified t) 20452 20453 (fontified t) 20453 20454 (face font-lock-operator-face fontified t) 20454 20455 (fontified t) 20455 20459 (face font-lock-constant-face fontified t) 20459 20460 (fontified t) 20460 20461 (face font-lock-operator-face fontified t) 20461 20462 (fontified t) 20462 20466 (face font-lock-constant-face fontified t) 20466 20471 (fontified t) 20471 20473 (face font-lock-doc-face fontified t) 20473 20474 (face font-lock-doc-face syntax-table (15) fontified t) 20474 20519 (face font-lock-doc-face fontified t) 20519 20520 (face font-lock-doc-face syntax-table (15) fontified t) 20520 20522 (face font-lock-doc-face fontified t) 20522 20535 (fontified t) 20535 20536 (prettify-symbols-end 20668 prettify-symbols-start 20667 composition (0 1 [32 65 57708]) fontified t) 20536 20537 (fontified t) 20537 20541 (face font-lock-builtin-face fontified t) 20541 20542 (fontified t) 20542 20543 (face font-lock-operator-face fontified t) 20543 20544 (fontified t) 20544 20548 (face font-lock-constant-face fontified t) 20548 20549 (fontified t) 20549 20550 (face font-lock-operator-face fontified t) 20550 20551 (fontified t) 20551 20555 (face font-lock-constant-face fontified t) 20555 20560 (fontified t) 20560 20562 (face font-lock-doc-face fontified t) 20562 20563 (face font-lock-doc-face syntax-table (15) fontified t) 20563 20602 (face font-lock-doc-face fontified t) 20602 20603 (face font-lock-doc-face syntax-table (15) fontified t) 20603 20605 (face font-lock-doc-face fontified t) 20605 20610 (fontified t) 20610 20622 (face font-lock-variable-name-face fontified t) 20622 20623 (fontified t) 20623 20624 (face font-lock-operator-face fontified t) 20624 20635 (fontified t) 20635 20636 (face (rainbow-delimiters-depth-1-face) fontified t) 20636 20641 (fontified t) 20641 20642 (face font-lock-operator-face fontified t) 20642 20649 (face font-lock-string-face fontified t) 20649 20650 (face (rainbow-delimiters-depth-1-face) fontified t) 20650 20653 (fontified t) 20653 20658 (face font-lock-keyword-face fontified t) 20658 20659 (fontified t) 20659 20665 (face font-lock-type-face fontified t) 20665 20666 (face (rainbow-delimiters-depth-1-face) fontified t) 20666 20678 (fontified t) 20678 20679 (face (rainbow-delimiters-depth-1-face) fontified t) 20679 20680 (prettify-symbols-end 20812 prettify-symbols-start 20811 composition (0 1 [32 65 57708]) fontified t) 20680 20685 (fontified t) 20685 20687 (face font-lock-doc-face fontified t) 20687 20688 (face font-lock-doc-face syntax-table (15) fontified t) 20688 20739 (face font-lock-doc-face fontified t) 20739 20740 (face font-lock-doc-face syntax-table (15) fontified t) 20740 20742 (face font-lock-doc-face fontified t) 20742 20751 (fontified t) 20751 20752 (prettify-symbols-end 20884 prettify-symbols-start 20883 composition (0 1 [32 65 57708]) fontified t) 20752 20762 (fontified t) 20762 20763 (face (rainbow-delimiters-depth-1-face) fontified t) 20763 20785 (fontified t) 20785 20786 (face (rainbow-delimiters-depth-2-face) fontified t) 20786 20801 (fontified t) 20801 20802 (face font-lock-operator-face fontified t) 20802 20803 (face (rainbow-delimiters-depth-3-face) fontified t) 20803 20811 (face font-lock-string-face fontified t) 20811 20812 (face (rainbow-delimiters-depth-3-face) fontified t) 20812 20827 (fontified t) 20827 20828 (face font-lock-operator-face fontified t) 20828 20833 (face font-lock-constant-face fontified t) 20833 20834 (face (rainbow-delimiters-depth-2-face) fontified t) 20834 20835 (face (rainbow-delimiters-depth-1-face) fontified t) 20835 20840 (fontified t) 20840 20842 (face font-lock-string-face fontified t) 20842 20843 (face font-lock-string-face syntax-table (15) fontified t) 20843 20888 (face font-lock-string-face fontified t) 20888 20889 (face font-lock-string-face syntax-table (15) fontified t) 20889 20891 (face font-lock-string-face fontified t) 20891 20907 (fontified t) 20907 20908 (prettify-symbols-end 21040 prettify-symbols-start 21039 composition (0 1 [32 65 57708]) fontified t) 20908 20909 (fontified t) 20909 20912 (face font-lock-builtin-face fontified t) 20912 20913 (fontified t) 20913 20914 (face font-lock-operator-face fontified t) 20914 20915 (fontified t) 20915 20919 (face font-lock-constant-face fontified t) 20919 20920 (fontified t) 20920 20921 (face font-lock-operator-face fontified t) 20921 20922 (fontified t) 20922 20926 (face font-lock-constant-face fontified t) 20926 20931 (fontified t) 20931 20933 (face font-lock-doc-face fontified t) 20933 20934 (face font-lock-doc-face syntax-table (15) fontified t) 20934 20987 (face font-lock-doc-face fontified t) 20987 20988 (face font-lock-doc-face syntax-table (15) fontified t) 20988 20990 (face font-lock-doc-face fontified t) 20990 21004 (fontified t) 21004 21005 (prettify-symbols-end 21137 prettify-symbols-start 21136 composition (0 1 [32 65 57708]) fontified t) 21005 21006 (fontified t) 21006 21010 (face font-lock-builtin-face fontified t) 21010 21011 (face (rainbow-delimiters-depth-1-face) fontified t) 21011 21025 (fontified t) 21025 21026 (face (rainbow-delimiters-depth-1-face) fontified t) 21026 21027 (fontified t) 21027 21028 (face font-lock-operator-face fontified t) 21028 21029 (fontified t) 21029 21033 (face font-lock-constant-face fontified t) 21033 21034 (fontified t) 21034 21035 (face font-lock-operator-face fontified t) 21035 21036 (fontified t) 21036 21040 (face font-lock-constant-face fontified t) 21040 21045 (fontified t) 21045 21047 (face font-lock-doc-face fontified t) 21047 21048 (face font-lock-doc-face syntax-table (15) fontified t) 21048 21101 (face font-lock-doc-face fontified t) 21101 21102 (face font-lock-doc-face syntax-table (15) fontified t) 21102 21104 (face font-lock-doc-face fontified t) 21104 21113 (fontified t) 21113 21114 (prettify-symbols-end 21246 prettify-symbols-start 21245 composition (0 1 [32 65 57708]) fontified t) 21114 21115 (fontified t) 21115 21119 (face font-lock-builtin-face fontified t) 21119 21120 (face (rainbow-delimiters-depth-1-face) fontified t) 21120 21123 (face font-lock-builtin-face fontified t) 21123 21128 (fontified t) 21128 21129 (face (rainbow-delimiters-depth-1-face) fontified t) 21129 21130 (fontified t) 21130 21131 (face font-lock-operator-face fontified t) 21131 21132 (fontified t) 21132 21136 (face font-lock-constant-face fontified t) 21136 21137 (fontified t) 21137 21138 (face font-lock-operator-face fontified t) 21138 21144 (fontified t) 21144 21145 (face (rainbow-delimiters-depth-1-face) fontified t) 21145 21150 (fontified t) 21150 21151 (face font-lock-operator-face fontified t) 21151 21158 (face font-lock-string-face fontified t) 21158 21167 (fontified t) 21167 21168 (face font-lock-operator-face fontified t) 21168 21172 (face font-lock-constant-face fontified t) 21172 21173 (face (rainbow-delimiters-depth-1-face) fontified t) 21173 21178 (fontified t) 21178 21180 (face font-lock-doc-face fontified t) 21180 21181 (face font-lock-doc-face syntax-table (15) fontified t) 21181 21408 (face font-lock-doc-face fontified t) 21408 21409 (face font-lock-doc-face syntax-table (15) fontified t) 21409 21411 (face font-lock-doc-face fontified t) 21411 21416 (fontified t) 21416 21428 (face font-lock-variable-name-face fontified t) 21428 21429 (fontified t) 21429 21430 (face font-lock-operator-face fontified t) 21430 21441 (fontified t) 21441 21442 (face (rainbow-delimiters-depth-1-face) fontified t) 21442 21447 (fontified t) 21447 21448 (face font-lock-operator-face fontified t) 21448 21455 (face font-lock-string-face fontified t) 21455 21456 (face (rainbow-delimiters-depth-1-face) fontified t) 21456 21459 (fontified t) 21459 21464 (face font-lock-keyword-face fontified t) 21464 21465 (fontified t) 21465 21482 (face font-lock-type-face fontified t) 21482 21483 (face (rainbow-delimiters-depth-1-face) fontified t) 21483 21493 (fontified t) 21493 21494 (face (rainbow-delimiters-depth-1-face) fontified t) 21494 21495 (prettify-symbols-end 21627 prettify-symbols-start 21626 composition (0 1 [32 65 57708]) fontified t) 21495 21500 (fontified t) 21500 21502 (face font-lock-doc-face fontified t) 21502 21503 (face font-lock-doc-face syntax-table (15) fontified t) 21503 21567 (face font-lock-doc-face fontified t) 21567 21568 (face font-lock-doc-face syntax-table (15) fontified t) 21568 21570 (face font-lock-doc-face fontified t) 21570 21583 (fontified t) 21583 21584 (prettify-symbols-end 21716 prettify-symbols-start 21715 composition (0 1 [32 65 57708]) fontified t) 21584 21585 (fontified t) 21585 21589 (face font-lock-builtin-face fontified t) 21589 21590 (face (rainbow-delimiters-depth-1-face) fontified t) 21590 21596 (fontified t) 21596 21597 (face (rainbow-delimiters-depth-1-face) fontified t) 21597 21600 (fontified t) 21600 21605 (face font-lock-keyword-face fontified t) 21605 21606 (fontified t) 21606 21628 (face font-lock-type-face fontified t) 21628 21629 (face (rainbow-delimiters-depth-1-face) fontified t) 21629 21642 (fontified t) 21642 21643 (face (rainbow-delimiters-depth-1-face) fontified t) 21643 21644 (prettify-symbols-end 21776 prettify-symbols-start 21775 composition (0 1 [32 65 57708]) fontified t) 21644 21649 (fontified t) 21649 21651 (face font-lock-doc-face fontified t) 21651 21652 (face font-lock-doc-face syntax-table (15) fontified t) 21652 21684 (face font-lock-doc-face fontified t) 21684 21685 (face font-lock-doc-face syntax-table (15) fontified t) 21685 21687 (face font-lock-doc-face fontified t) 21687 21697 (fontified t) 21697 21698 (prettify-symbols-end 21830 prettify-symbols-start 21829 composition (0 1 [32 65 57708]) fontified t) 21698 21699 (fontified t) 21699 21702 (face font-lock-builtin-face fontified t) 21702 21707 (fontified t) 21707 21709 (face font-lock-string-face fontified t) 21709 21710 (face font-lock-string-face syntax-table (15) fontified t) 21710 21752 (face font-lock-string-face fontified t) 21752 21753 (face font-lock-string-face syntax-table (15) fontified t) 21753 21755 (face font-lock-string-face fontified t) 21755 21769 (fontified t) 21769 21770 (prettify-symbols-end 21902 prettify-symbols-start 21901 composition (0 1 [32 65 57708]) fontified t) 21770 21771 (fontified t) 21771 21775 (face font-lock-builtin-face fontified t) 21775 21776 (face (rainbow-delimiters-depth-1-face) fontified t) 21776 21779 (face font-lock-builtin-face fontified t) 21779 21781 (fontified t) 21781 21784 (face font-lock-builtin-face fontified t) 21784 21785 (face (rainbow-delimiters-depth-1-face) fontified t) 21785 21786 (fontified t) 21786 21787 (face font-lock-operator-face fontified t) 21787 21788 (fontified t) 21788 21792 (face font-lock-constant-face fontified t) 21792 21793 (fontified t) 21793 21794 (face font-lock-operator-face fontified t) 21794 21795 (fontified t) 21795 21799 (face font-lock-constant-face fontified t) 21799 21804 (fontified t) 21804 21806 (face font-lock-doc-face fontified t) 21806 21807 (face font-lock-doc-face syntax-table (15) fontified t) 21807 21850 (face font-lock-doc-face fontified t) 21850 21851 (face font-lock-doc-face syntax-table (15) fontified t) 21851 21853 (face font-lock-doc-face fontified t) 21853 21858 (fontified t) 21858 21870 (face font-lock-variable-name-face fontified t) 21870 21871 (fontified t) 21871 21872 (face font-lock-operator-face fontified t) 21872 21883 (fontified t) 21883 21884 (face (rainbow-delimiters-depth-1-face) fontified t) 21884 21889 (fontified t) 21889 21890 (face font-lock-operator-face fontified t) 21890 21897 (face font-lock-string-face fontified t) 21897 21898 (face (rainbow-delimiters-depth-1-face) fontified t) 21898 21901 (fontified t) 21901 21906 (face font-lock-keyword-face fontified t) 21906 21907 (fontified t) 21907 21923 (face font-lock-type-face fontified t) 21923 21924 (face (rainbow-delimiters-depth-1-face) fontified t) 21924 21931 (fontified t) 21931 21932 (face (rainbow-delimiters-depth-2-face) fontified t) 21932 21963 (fontified t) 21963 21964 (face (rainbow-delimiters-depth-3-face) fontified t) 21964 21977 (face font-lock-string-face fontified t) 21977 21978 (face (rainbow-delimiters-depth-3-face) fontified t) 21978 21979 (face (rainbow-delimiters-depth-2-face) fontified t) 21979 21980 (face (rainbow-delimiters-depth-1-face) fontified t) 21980 21981 (prettify-symbols-end 22113 prettify-symbols-start 22112 composition (0 1 [32 65 57708]) fontified t) 21981 21986 (fontified t) 21986 21988 (face font-lock-doc-face fontified t) 21988 21989 (face font-lock-doc-face syntax-table (15) fontified t) 21989 22047 (face font-lock-doc-face fontified t) 22047 22048 (face font-lock-doc-face syntax-table (15) fontified t) 22048 22050 (face font-lock-doc-face fontified t) 22050 22062 (fontified t) 22062 22063 (prettify-symbols-end 22195 prettify-symbols-start 22194 composition (0 1 [32 65 57708]) fontified t) 22063 22071 (fontified t) 22071 22072 (face (rainbow-delimiters-depth-1-face) fontified t) 22072 22085 (face font-lock-string-face fontified t) 22085 22086 (face (rainbow-delimiters-depth-1-face) fontified t) 22086 22097 (fontified t) 22097 22098 (prettify-symbols-end 22230 prettify-symbols-start 22229 composition (0 1 [32 65 57708]) fontified t) 22098 22124 (fontified t) 22124 22129 (face font-lock-keyword-face fontified t) 22129 22130 (fontified t) 22130 22141 (face font-lock-type-face fontified t) 22141 22142 (face (rainbow-delimiters-depth-1-face) fontified t) 22142 22151 (fontified t) 22151 22152 (face (rainbow-delimiters-depth-1-face) fontified t) 22152 22153 (prettify-symbols-end 22285 prettify-symbols-start 22284 composition (0 1 [32 65 57708]) fontified t) 22153 22158 (fontified t) 22158 22160 (face font-lock-doc-face fontified t) 22160 22161 (face font-lock-doc-face syntax-table (15) fontified t) 22161 22188 (face font-lock-doc-face fontified t) 22188 22189 (face font-lock-doc-face syntax-table (15) fontified t) 22189 22191 (face font-lock-doc-face fontified t) 22191 22197 (fontified t) 22197 22201 (face font-lock-builtin-face fontified t) 22201 22202 (prettify-symbols-end 22334 prettify-symbols-start 22333 composition (0 1 [32 65 57708]) fontified t) 22202 22210 (fontified t) 22210 22211 (face (rainbow-delimiters-depth-1-face) fontified t) 22211 22217 (face font-lock-string-face fontified t) 22217 22218 (face (rainbow-delimiters-depth-1-face) fontified t) 22218 22227 (fontified t) 22227 22228 (prettify-symbols-end 22360 prettify-symbols-start 22359 composition (0 1 [32 65 57708]) fontified t) 22228 22229 (fontified t) 22229 22232 (face font-lock-builtin-face fontified t) 22232 22237 (fontified t) 22237 22239 (face font-lock-string-face fontified t) 22239 22240 (face font-lock-string-face syntax-table (15) fontified t) 22240 22272 (face font-lock-string-face fontified t) 22272 22273 (face font-lock-string-face syntax-table (15) fontified t) 22273 22275 (face font-lock-string-face fontified t) 22275 22291 (fontified t) 22291 22292 (prettify-symbols-end 22424 prettify-symbols-start 22423 composition (0 1 [32 65 57708]) fontified t) 22292 22305 (fontified t) 22305 22306 (face font-lock-operator-face fontified t) 22306 22307 (fontified t) 22307 22311 (face font-lock-constant-face fontified t) 22311 22312 (fontified t) 22312 22313 (face font-lock-operator-face fontified t) 22313 22314 (fontified t) 22314 22318 (face font-lock-constant-face fontified t) 22318 22327 (fontified t) 22327 22328 (prettify-symbols-end 22460 prettify-symbols-start 22459 composition (0 1 [32 65 57708]) fontified t) 22328 22329 (fontified t) 22329 22333 (face font-lock-builtin-face fontified t) 22333 22334 (face (rainbow-delimiters-depth-1-face) fontified t) 22334 22337 (face font-lock-builtin-face fontified t) 22337 22342 (fontified t) 22342 22343 (face (rainbow-delimiters-depth-1-face) fontified t) 22343 22344 (fontified t) 22344 22345 (face font-lock-operator-face fontified t) 22345 22346 (fontified t) 22346 22350 (face font-lock-constant-face fontified t) 22350 22351 (fontified t) 22351 22352 (face font-lock-operator-face fontified t) 22352 22358 (fontified t) 22358 22359 (face (rainbow-delimiters-depth-1-face) fontified t) 22359 22364 (fontified t) 22364 22365 (face font-lock-operator-face fontified t) 22365 22372 (face font-lock-string-face fontified t) 22372 22381 (fontified t) 22381 22382 (face font-lock-operator-face fontified t) 22382 22386 (face font-lock-constant-face fontified t) 22386 22387 (face (rainbow-delimiters-depth-1-face) fontified t) 22387 22392 (fontified t) 22392 22394 (face font-lock-doc-face fontified t) 22394 22395 (face font-lock-doc-face syntax-table (15) fontified t) 22395 22622 (face font-lock-doc-face fontified t) 22622 22623 (face font-lock-doc-face syntax-table (15) fontified t) 22623 22625 (face font-lock-doc-face fontified t) 22625 22630 (fontified t) 22630 22642 (face font-lock-variable-name-face fontified t) 22642 22643 (fontified t) 22643 22644 (face font-lock-operator-face fontified t) 22644 22655 (fontified t) 22655 22656 (face (rainbow-delimiters-depth-1-face) fontified t) 22656 22661 (fontified t) 22661 22662 (face font-lock-operator-face fontified t) 22662 22669 (face font-lock-string-face fontified t) 22669 22670 (face (rainbow-delimiters-depth-1-face) fontified t) 22670 22673 (fontified t) 22673 22678 (face font-lock-keyword-face fontified t) 22678 22679 (fontified t) 22679 22691 (face font-lock-type-face fontified t) 22691 22692 (face (rainbow-delimiters-depth-1-face) fontified t) 22692 22701 (fontified t) 22701 22702 (face (rainbow-delimiters-depth-1-face) fontified t) 22702 22703 (prettify-symbols-end 22835 prettify-symbols-start 22834 composition ((1 32 65 57708)) fontified t) 22703 22708 (fontified t) 22708 22710 (face font-lock-doc-face fontified t) 22710 22711 (face font-lock-doc-face syntax-table (15) fontified t) 22711 22739 (face font-lock-doc-face fontified t) 22739 22740 (face font-lock-doc-face syntax-table (15) fontified t) 22740 22742 (face font-lock-doc-face fontified t) 22742 22748 (fontified t) 22748 22752 (face font-lock-builtin-face fontified t) 22752 22753 (prettify-symbols-end 22885 prettify-symbols-start 22884 composition ((1 32 65 57708)) fontified t) 22753 22761 (fontified t) 22761 22762 (face (rainbow-delimiters-depth-1-face) fontified t) 22762 22769 (face font-lock-string-face fontified t) 22769 22770 (face (rainbow-delimiters-depth-1-face) fontified t) 22770 22779 (fontified t) 22779 22780 (prettify-symbols-end 22912 prettify-symbols-start 22911 composition ((1 32 65 57708)) fontified t) 22780 22781 (fontified t) 22781 22784 (face font-lock-builtin-face fontified t) 22784 22789 (fontified t) 22789 22791 (face font-lock-string-face fontified t) 22791 22792 (face font-lock-string-face syntax-table (15) fontified t) 22792 22822 (face font-lock-string-face fontified t) 22822 22823 (face font-lock-string-face syntax-table (15) fontified t) 22823 22825 (face font-lock-string-face fontified t) 22825 22838 (fontified t) 22838 22839 (prettify-symbols-end 22971 prettify-symbols-start 22970 composition ((1 32 65 57708)) fontified t) 22839 22840 (fontified t) 22840 22843 (face font-lock-builtin-face fontified t) 22843 22848 (fontified t) 22848 22850 (face font-lock-string-face fontified t) 22850 22851 (face font-lock-string-face syntax-table (15) fontified t) 22851 22947 (face font-lock-string-face fontified t) 22947 22948 (face font-lock-string-face syntax-table (15) fontified t) 22948 22950 (face font-lock-string-face fontified t) 22950 22966 (fontified t) 22966 22967 (prettify-symbols-end 23099 prettify-symbols-start 23098 composition ((1 32 65 57708)) fontified t) 22967 22980 (fontified t) 22980 22981 (face font-lock-operator-face fontified t) 22981 22982 (fontified t) 22982 22986 (face font-lock-constant-face fontified t) 22986 22987 (fontified t) 22987 22988 (face font-lock-operator-face fontified t) 22988 22989 (fontified t) 22989 22993 (face font-lock-constant-face fontified t) 22993 23002 (fontified t) 23002 23003 (prettify-symbols-end 23135 prettify-symbols-start 23134 composition ((1 32 65 57708)) fontified t) 23003 23004 (fontified t) 23004 23008 (face font-lock-builtin-face fontified t) 23008 23009 (face (rainbow-delimiters-depth-1-face) fontified t) 23009 23012 (face font-lock-builtin-face fontified t) 23012 23017 (fontified t) 23017 23018 (face (rainbow-delimiters-depth-1-face) fontified t) 23018 23019 (fontified t) 23019 23020 (face font-lock-operator-face fontified t) 23020 23021 (fontified t) 23021 23025 (face font-lock-constant-face fontified t) 23025 23026 (fontified t) 23026 23027 (face font-lock-operator-face fontified t) 23027 23033 (fontified t) 23033 23034 (face (rainbow-delimiters-depth-1-face) fontified t) 23034 23039 (fontified t) 23039 23040 (face font-lock-operator-face fontified t) 23040 23047 (face font-lock-string-face fontified t) 23047 23056 (fontified t) 23056 23057 (face font-lock-operator-face fontified t) 23057 23061 (face font-lock-constant-face fontified t) 23061 23062 (face (rainbow-delimiters-depth-1-face) fontified t) 23062 23067 (fontified t) 23067 23069 (face font-lock-doc-face fontified t) 23069 23070 (face font-lock-doc-face syntax-table (15) fontified t) 23070 23297 (face font-lock-doc-face fontified t) 23297 23298 (face font-lock-doc-face syntax-table (15) fontified t) 23298 23300 (face font-lock-doc-face fontified t) 23300 23305 (fontified t) 23305 23317 (face font-lock-variable-name-face fontified t) 23317 23318 (fontified t) 23318 23319 (face font-lock-operator-face fontified t) 23319 23330 (fontified t) 23330 23331 (face (rainbow-delimiters-depth-1-face) fontified t) 23331 23336 (fontified t) 23336 23337 (face font-lock-operator-face fontified t) 23337 23344 (face font-lock-string-face fontified t) 23344 23345 (face (rainbow-delimiters-depth-1-face) fontified t) 23345 23348 (fontified t) 23348 23353 (face font-lock-keyword-face fontified t) 23353 23354 (fontified t) 23354 23366 (face font-lock-type-face fontified t) 23366 23367 (face (rainbow-delimiters-depth-1-face) fontified t) 23367 23376 (fontified t) 23376 23377 (face (rainbow-delimiters-depth-1-face) fontified t) 23377 23378 (prettify-symbols-end 23510 prettify-symbols-start 23509 composition ((1 32 65 57708)) fontified t) 23378 23383 (fontified t) 23383 23385 (face font-lock-doc-face fontified t) 23385 23386 (face font-lock-doc-face syntax-table (15) fontified t) 23386 23414 (face font-lock-doc-face fontified t) 23414 23415 (face font-lock-doc-face syntax-table (15) fontified t) 23415 23417 (face font-lock-doc-face fontified t) 23417 23423 (fontified t) 23423 23427 (face font-lock-builtin-face fontified t) 23427 23428 (prettify-symbols-end 23560 prettify-symbols-start 23559 composition ((1 32 65 57708)) fontified t) 23428 23436 (fontified t) 23436 23437 (face (rainbow-delimiters-depth-1-face) fontified t) 23437 23444 (face font-lock-string-face fontified t) 23444 23445 (face (rainbow-delimiters-depth-1-face) fontified t) 23445 23454 (fontified t) 23454 23455 (prettify-symbols-end 23587 prettify-symbols-start 23586 composition ((1 32 65 57708)) fontified t) 23455 23456 (fontified t) 23456 23459 (face font-lock-builtin-face fontified t) 23459 23464 (fontified t) 23464 23466 (face font-lock-string-face fontified t) 23466 23467 (face font-lock-string-face syntax-table (15) fontified t) 23467 23497 (face font-lock-string-face fontified t) 23497 23498 (face font-lock-string-face syntax-table (15) fontified t) 23498 23500 (face font-lock-string-face fontified t) 23500 23513 (fontified t) 23513 23514 (prettify-symbols-end 23646 prettify-symbols-start 23645 composition ((1 32 65 57708)) fontified t) 23514 23515 (fontified t) 23515 23518 (face font-lock-builtin-face fontified t) 23518 23523 (fontified t) 23523 23525 (face font-lock-string-face fontified t) 23525 23526 (face font-lock-string-face syntax-table (15) fontified t) 23526 23622 (face font-lock-string-face fontified t) 23622 23623 (face font-lock-string-face syntax-table (15) fontified t) 23623 23625 (face font-lock-string-face fontified t) 23625 23641 (fontified t) 23641 23642 (prettify-symbols-end 23774 prettify-symbols-start 23773 composition ((1 32 65 57708)) fontified t) 23642 23655 (fontified t) 23655 23656 (face font-lock-operator-face fontified t) 23656 23657 (fontified t) 23657 23661 (face font-lock-constant-face fontified t) 23661 23662 (fontified t) 23662 23663 (face font-lock-operator-face fontified t) 23663 23664 (fontified t) 23664 23668 (face font-lock-constant-face fontified t) 23668 23677 (fontified t) 23677 23678 (prettify-symbols-end 23810 prettify-symbols-start 23809 composition ((1 32 65 57708)) fontified t) 23678 23679 (fontified t) 23679 23683 (face font-lock-builtin-face fontified t) 23683 23684 (face (rainbow-delimiters-depth-1-face) fontified t) 23684 23687 (face font-lock-builtin-face fontified t) 23687 23692 (fontified t) 23692 23693 (face (rainbow-delimiters-depth-1-face) fontified t) 23693 23694 (fontified t) 23694 23695 (face font-lock-operator-face fontified t) 23695 23696 (fontified t) 23696 23700 (face font-lock-constant-face fontified t) 23700 23701 (fontified t) 23701 23702 (face font-lock-operator-face fontified t) 23702 23708 (fontified t) 23708 23709 (face (rainbow-delimiters-depth-1-face) fontified t) 23709 23714 (fontified t) 23714 23715 (face font-lock-operator-face fontified t) 23715 23722 (face font-lock-string-face fontified t) 23722 23731 (fontified t) 23731 23732 (face font-lock-operator-face fontified t) 23732 23736 (face font-lock-constant-face fontified t) 23736 23737 (face (rainbow-delimiters-depth-1-face) fontified t) 23737 23742 (fontified t) 23742 23744 (face font-lock-doc-face fontified t) 23744 23745 (face font-lock-doc-face syntax-table (15) fontified t) 23745 23972 (face font-lock-doc-face fontified t) 23972 23973 (face font-lock-doc-face syntax-table (15) fontified t) 23973 23975 (face font-lock-doc-face fontified t) 23975 23980 (fontified t) 23980 23992 (face font-lock-variable-name-face fontified t) 23992 23993 (fontified t) 23993 23994 (face font-lock-operator-face fontified t) 23994 24005 (fontified t) 24005 24006 (face (rainbow-delimiters-depth-1-face) fontified t) 24006 24011 (fontified t) 24011 24012 (face font-lock-operator-face fontified t) 24012 24019 (face font-lock-string-face fontified t) 24019 24020 (face (rainbow-delimiters-depth-1-face) fontified t) 24020 24023 (fontified t) 24023 24028 (face font-lock-keyword-face fontified t) 24028 24029 (fontified t) 24029 24044 (face font-lock-type-face fontified t) 24044 24045 (face (rainbow-delimiters-depth-1-face) fontified t) 24045 24054 (fontified t) 24054 24055 (face (rainbow-delimiters-depth-1-face) fontified t) 24055 24056 (prettify-symbols-end 24188 prettify-symbols-start 24187 composition ((1 32 65 57708)) fontified t) 24056 24061 (fontified t) 24061 24063 (face font-lock-doc-face fontified t) 24063 24064 (face font-lock-doc-face syntax-table (15) fontified t) 24064 24122 (face font-lock-doc-face fontified t) 24122 24123 (face font-lock-doc-face syntax-table (15) fontified t) 24123 24125 (face font-lock-doc-face fontified t) 24125 24135 (fontified t) 24135 24136 (prettify-symbols-end 24268 prettify-symbols-start 24267 composition ((1 32 65 57708)) fontified t) 24136 24153 (fontified t) 24153 24154 (prettify-symbols-end 24286 prettify-symbols-start 24285 composition ((1 32 65 57708)) fontified t) 24154 24167 (fontified t) 24167 24168 (face font-lock-operator-face fontified t) 24168 24182 (fontified t) 24182 24183 (face font-lock-operator-face fontified t) 24183 24201 (fontified t) 24201 24213 (face font-lock-variable-name-face fontified t) 24213 24214 (fontified t) 24214 24215 (face font-lock-operator-face fontified t) 24215 24226 (fontified t) 24226 24227 (face (rainbow-delimiters-depth-1-face) fontified t) 24227 24232 (fontified t) 24232 24233 (face font-lock-operator-face fontified t) 24233 24240 (face font-lock-string-face fontified t) 24240 24241 (face (rainbow-delimiters-depth-1-face) fontified t) 24241 24244 (fontified t) 24244 24249 (face font-lock-keyword-face fontified t) 24249 24250 (fontified t) 24250 24266 (face font-lock-type-face fontified t) 24266 24267 (face (rainbow-delimiters-depth-1-face) fontified t) 24267 24276 (fontified t) 24276 24277 (face (rainbow-delimiters-depth-1-face) fontified t) 24277 24278 (prettify-symbols-end 24410 prettify-symbols-start 24409 composition ((1 32 65 57708)) fontified t) 24278 24283 (fontified t) 24283 24285 (face font-lock-doc-face fontified t) 24285 24286 (face font-lock-doc-face syntax-table (15) fontified t) 24286 24481 (face font-lock-doc-face fontified t) 24481 24482 (face font-lock-doc-face syntax-table (15) fontified t) 24482 24484 (face font-lock-doc-face fontified t) 24484 24490 (fontified t) 24490 24494 (face font-lock-builtin-face fontified t) 24494 24495 (prettify-symbols-end 24627 prettify-symbols-start 24626 composition ((1 32 65 57708)) fontified t) 24495 24503 (fontified t) 24503 24504 (face (rainbow-delimiters-depth-1-face) fontified t) 24504 24514 (face font-lock-string-face fontified t) 24514 24515 (face (rainbow-delimiters-depth-1-face) fontified t) 24515 24528 (fontified t) 24528 24529 (prettify-symbols-end 24661 prettify-symbols-start 24660 composition ((1 32 65 57708)) fontified t) 24529 24551 (fontified t) 24551 24552 (face font-lock-operator-face fontified t) 24552 24589 (fontified t) 24589 24590 (prettify-symbols-end 24722 prettify-symbols-start 24721 composition ((1 32 65 57708)) fontified t) 24590 24603 (fontified t) 24603 24604 (face font-lock-operator-face fontified t) 24604 24605 (fontified t) 24605 24609 (face font-lock-constant-face fontified t) 24609 24610 (fontified t) 24610 24611 (face font-lock-operator-face fontified t) 24611 24612 (fontified t) 24612 24616 (face font-lock-constant-face fontified t) 24616 24625 (fontified t) 24625 24626 (prettify-symbols-end 24758 prettify-symbols-start 24757 composition ((1 32 65 57708)) fontified t) 24626 24627 (fontified t) 24627 24631 (face font-lock-builtin-face fontified t) 24631 24632 (face (rainbow-delimiters-depth-1-face) fontified t) 24632 24635 (face font-lock-builtin-face fontified t) 24635 24640 (fontified t) 24640 24641 (face (rainbow-delimiters-depth-1-face) fontified t) 24641 24642 (fontified t) 24642 24643 (face font-lock-operator-face fontified t) 24643 24644 (fontified t) 24644 24648 (face font-lock-constant-face fontified t) 24648 24649 (fontified t) 24649 24650 (face font-lock-operator-face fontified t) 24650 24656 (fontified t) 24656 24657 (face (rainbow-delimiters-depth-1-face) fontified t) 24657 24662 (fontified t) 24662 24663 (face font-lock-operator-face fontified t) 24663 24670 (face font-lock-string-face fontified t) 24670 24679 (fontified t) 24679 24680 (face font-lock-operator-face fontified t) 24680 24684 (face font-lock-constant-face fontified t) 24684 24685 (face (rainbow-delimiters-depth-1-face) fontified t) 24685 24690 (fontified t) 24690 24692 (face font-lock-doc-face fontified t) 24692 24693 (face font-lock-doc-face syntax-table (15) fontified t) 24693 24920 (face font-lock-doc-face fontified t) 24920 24921 (face font-lock-doc-face syntax-table (15) fontified t) 24921 24923 (face font-lock-doc-face fontified t) 24923 24928 (fontified t) 24928 24940 (face font-lock-variable-name-face fontified t) 24940 24941 (fontified t) 24941 24942 (face font-lock-operator-face fontified t) 24942 24953 (fontified t) 24953 24954 (face (rainbow-delimiters-depth-1-face) fontified t) 24954 24959 (fontified t) 24959 24960 (face font-lock-operator-face fontified t) 24960 24967 (face font-lock-string-face fontified t) 24967 24968 (face (rainbow-delimiters-depth-1-face) fontified t) 24968 24971 (fontified t) 24971 24976 (face font-lock-keyword-face fontified t) 24976 24977 (fontified t) 24977 24989 (face font-lock-type-face fontified t) 24989 24990 (face (rainbow-delimiters-depth-1-face) fontified t) 24990 24998 (fontified t) 24998 24999 (face (rainbow-delimiters-depth-1-face) fontified t) 24999 25000 (prettify-symbols-end 25132 prettify-symbols-start 25131 composition ((1 32 65 57708)) fontified t) 25000 25005 (fontified t) 25005 25007 (face font-lock-doc-face fontified t) 25007 25008 (face font-lock-doc-face syntax-table (15) fontified t) 25008 25227 (face font-lock-doc-face fontified t) 25227 25228 (face font-lock-doc-face syntax-table (15) fontified t) 25228 25230 (face font-lock-doc-face fontified t) 25230 25236 (fontified t) 25236 25240 (face font-lock-builtin-face fontified t) 25240 25241 (prettify-symbols-end 25373 prettify-symbols-start 25372 composition ((1 32 65 57708)) fontified t) 25241 25249 (fontified t) 25249 25250 (face (rainbow-delimiters-depth-1-face) fontified t) 25250 25265 (face font-lock-string-face fontified t) 25265 25266 (face (rainbow-delimiters-depth-1-face) fontified t) 25266 25269 (fontified t) 25269 25281 (face font-lock-variable-name-face fontified t) 25281 25282 (fontified t) 25282 25283 (face font-lock-operator-face fontified t) 25283 25296 (fontified t) 25296 25297 (face font-lock-operator-face fontified t) 25297 25311 (fontified t) 25311 25312 (face font-lock-operator-face fontified t) 25312 25326 (fontified t) 25326 25327 (face font-lock-operator-face fontified t) 25327 25341 (fontified t) 25341 25342 (face font-lock-operator-face fontified t) 25342 25360 (fontified t) 25360 25362 (face font-lock-doc-face fontified t) 25362 25363 (face font-lock-doc-face syntax-table (15) fontified t) 25363 25424 (face font-lock-doc-face fontified t) 25424 25425 (face font-lock-doc-face syntax-table (15) fontified t) 25425 25427 (face font-lock-doc-face fontified t) 25427 25429 (fontified t) 25429 25436 (face font-lock-variable-name-face fontified t) 25436 25437 (prettify-symbols-end 25569 prettify-symbols-start 25568 composition ((1 32 65 57708)) fontified t) 25437 25448 (fontified t) 25448 25449 (face font-lock-operator-face fontified t) 25449 25463 (fontified t) 25463 25465 (face font-lock-comment-delimiter-face fontified t) 25465 25544 (face font-lock-comment-face fontified t) 25544 25546 (fontified t) 25546 25551 (face font-lock-keyword-face fontified t) 25551 25552 (fontified t) 25552 25565 (face font-lock-type-face fontified t) 25565 25566 (face (rainbow-delimiters-depth-1-face) fontified t) 25566 25575 (fontified t) 25575 25576 (face (rainbow-delimiters-depth-1-face) fontified t) 25576 25577 (prettify-symbols-end 25709 prettify-symbols-start 25708 composition (0 1 [32 65 57708]) fontified t) 25577 25582 (fontified t) 25582 25584 (face font-lock-doc-face fontified t) 25584 25585 (face font-lock-doc-face syntax-table (15) fontified t) 25585 25634 (face font-lock-doc-face fontified t) 25634 25635 (face font-lock-doc-face syntax-table (15) fontified t) 25635 25637 (face font-lock-doc-face fontified t) 25637 25647 (fontified t) 25647 25648 (prettify-symbols-end 25780 prettify-symbols-start 25779 composition (0 1 [32 65 57708]) fontified t) 25648 25665 (fontified t) 25665 25666 (prettify-symbols-end 25798 prettify-symbols-start 25797 composition (0 1 [32 65 57708]) fontified t) 25666 25684 (fontified t) 25684 25696 (face font-lock-variable-name-face fontified t) 25696 25697 (fontified t) 25697 25698 (face font-lock-operator-face fontified t) 25698 25709 (fontified t) 25709 25710 (face (rainbow-delimiters-depth-1-face) fontified t) 25710 25715 (fontified t) 25715 25716 (face font-lock-operator-face fontified t) 25716 25723 (face font-lock-string-face fontified t) 25723 25724 (face (rainbow-delimiters-depth-1-face) fontified t) 25724 25727 (fontified t) 25727 25732 (face font-lock-keyword-face fontified t) 25732 25733 (fontified t) 25733 25748 (face font-lock-type-face fontified t) 25748 25749 (face (rainbow-delimiters-depth-1-face) fontified t) 25749 25755 (fontified t) 25755 25756 (face (rainbow-delimiters-depth-1-face) fontified t) 25756 25757 (prettify-symbols-end 25889 prettify-symbols-start 25888 composition (0 1 [32 65 57708]) fontified t) 25757 25762 (fontified t) 25762 25764 (face font-lock-doc-face fontified t) 25764 25765 (face font-lock-doc-face syntax-table (15) fontified t) 25765 25828 (face font-lock-doc-face fontified t) 25828 25829 (face font-lock-doc-face syntax-table (15) fontified t) 25829 25831 (face font-lock-doc-face fontified t) 25831 25848 (fontified t) 25848 25849 (prettify-symbols-end 25981 prettify-symbols-start 25980 composition (0 1 [32 65 57708]) fontified t) 25849 25850 (fontified t) 25850 25853 (face font-lock-builtin-face fontified t) 25853 25854 (fontified t) 25854 25855 (face font-lock-operator-face fontified t) 25855 25856 (fontified t) 25856 25860 (face font-lock-constant-face fontified t) 25860 25861 (fontified t) 25861 25862 (face font-lock-operator-face fontified t) 25862 25863 (fontified t) 25863 25867 (face font-lock-constant-face fontified t) 25867 25872 (fontified t) 25872 25874 (face font-lock-doc-face fontified t) 25874 25875 (face font-lock-doc-face syntax-table (15) fontified t) 25875 25914 (face font-lock-doc-face fontified t) 25914 25915 (face font-lock-doc-face syntax-table (15) fontified t) 25915 25917 (face font-lock-doc-face fontified t) 25917 25930 (fontified t) 25930 25931 (prettify-symbols-end 26063 prettify-symbols-start 26062 composition (0 1 [32 65 57708]) fontified t) 25931 25932 (fontified t) 25932 25936 (face font-lock-builtin-face fontified t) 25936 25937 (face (rainbow-delimiters-depth-1-face) fontified t) 25937 25950 (fontified t) 25950 25951 (face (rainbow-delimiters-depth-1-face) fontified t) 25951 25954 (fontified t) 25954 25959 (face font-lock-keyword-face fontified t) 25959 25960 (fontified t) 25960 25989 (face font-lock-type-face fontified t) 25989 25990 (face (rainbow-delimiters-depth-1-face) fontified t) 25990 26007 (fontified t) 26007 26008 (face (rainbow-delimiters-depth-2-face) fontified t) 26008 26027 (fontified t) 26027 26028 (face font-lock-operator-face fontified t) 26028 26029 (fontified t) 26029 26033 (face font-lock-constant-face fontified t) 26033 26042 (fontified t) 26042 26043 (face (rainbow-delimiters-depth-3-face) fontified t) 26043 26079 (face font-lock-string-face fontified t) 26079 26080 (face (rainbow-delimiters-depth-3-face) fontified t) 26080 26081 (face (rainbow-delimiters-depth-2-face) fontified t) 26081 26082 (fontified t) 26082 26083 (face (rainbow-delimiters-depth-1-face) fontified t) 26083 26084 (prettify-symbols-end 26216 prettify-symbols-start 26215 composition (0 1 [32 65 57708]) fontified t) 26084 26089 (fontified t) 26089 26091 (face font-lock-doc-face fontified t) 26091 26092 (face font-lock-doc-face syntax-table (15) fontified t) 26092 26222 (face font-lock-doc-face fontified t) 26222 26223 (face font-lock-doc-face syntax-table (15) fontified t) 26223 26225 (face font-lock-doc-face fontified t) 26225 26237 (fontified t) 26237 26238 (prettify-symbols-end 26370 prettify-symbols-start 26369 composition (0 1 [32 65 57708]) fontified t) 26238 26246 (fontified t) 26246 26247 (face (rainbow-delimiters-depth-1-face) fontified t) 26247 26283 (face font-lock-string-face fontified t) 26283 26284 (face (rainbow-delimiters-depth-1-face) fontified t) 26284 26295 (fontified t) 26295 26296 (prettify-symbols-end 26428 prettify-symbols-start 26427 composition (0 1 [32 65 57708]) fontified t) 26296 26316 (fontified t) 26316 26317 (face font-lock-operator-face fontified t) 26317 26318 (fontified t) 26318 26322 (face font-lock-constant-face fontified t) 26322 26323 (fontified t) 26323 26324 (face font-lock-operator-face fontified t) 26324 26325 (fontified t) 26325 26329 (face font-lock-constant-face fontified t) 26329 26332 (fontified t) 26332 26337 (face font-lock-keyword-face fontified t) 26337 26338 (fontified t) 26338 26354 (face font-lock-type-face fontified t) 26354 26355 (face (rainbow-delimiters-depth-1-face) fontified t) 26355 26366 (fontified t) 26366 26367 (face (rainbow-delimiters-depth-2-face) fontified t) 26367 26374 (fontified t) 26374 26375 (face (rainbow-delimiters-depth-3-face) fontified t) 26375 26387 (face font-lock-string-face fontified t) 26387 26388 (face (rainbow-delimiters-depth-3-face) fontified t) 26388 26389 (face (rainbow-delimiters-depth-2-face) fontified t) 26389 26390 (face (rainbow-delimiters-depth-1-face) fontified t) 26390 26391 (prettify-symbols-end 26523 prettify-symbols-start 26522 composition (0 1 [32 65 57708]) fontified t) 26391 26396 (fontified t) 26396 26398 (face font-lock-doc-face fontified t) 26398 26399 (face font-lock-doc-face syntax-table (15) fontified t) 26399 26462 (face font-lock-doc-face fontified t) 26462 26463 (face font-lock-doc-face syntax-table (15) fontified t) 26463 26465 (face font-lock-doc-face fontified t) 26465 26477 (fontified t) 26477 26478 (prettify-symbols-end 26610 prettify-symbols-start 26609 composition (0 1 [32 65 57708]) fontified t) 26478 26486 (fontified t) 26486 26487 (face (rainbow-delimiters-depth-1-face) fontified t) 26487 26499 (face font-lock-string-face fontified t) 26499 26500 (face (rainbow-delimiters-depth-1-face) fontified t) 26500 26503 (fontified t) 26503 26508 (face font-lock-keyword-face fontified t) 26508 26509 (fontified t) 26509 26524 (face font-lock-type-face fontified t) 26524 26525 (face (rainbow-delimiters-depth-1-face) fontified t) 26525 26534 (fontified t) 26534 26535 (face (rainbow-delimiters-depth-1-face) fontified t) 26535 26536 (prettify-symbols-end 26668 prettify-symbols-start 26667 composition (0 1 [32 65 57708]) fontified t) 26536 26541 (fontified t) 26541 26543 (face font-lock-doc-face fontified t) 26543 26544 (face font-lock-doc-face syntax-table (15) fontified t) 26544 26909 (face font-lock-doc-face fontified t) 26909 26910 (face font-lock-doc-face syntax-table (15) fontified t) 26910 26912 (face font-lock-doc-face fontified t) 26912 26923 (fontified t) 26923 26924 (prettify-symbols-end 27056 prettify-symbols-start 27055 composition (0 1 [32 65 57708]) fontified t) 26924 26925 (fontified t) 26925 26928 (face font-lock-builtin-face fontified t) 26928 26929 (fontified t) 26929 26930 (face font-lock-operator-face fontified t) 26930 26931 (fontified t) 26931 26935 (face font-lock-constant-face fontified t) 26935 26936 (fontified t) 26936 26937 (face font-lock-operator-face fontified t) 26937 26938 (fontified t) 26938 26942 (face font-lock-constant-face fontified t) 26942 26947 (fontified t) 26947 26949 (face font-lock-doc-face fontified t) 26949 26950 (face font-lock-doc-face syntax-table (15) fontified t) 26950 26986 (face font-lock-doc-face fontified t) 26986 26987 (face font-lock-doc-face syntax-table (15) fontified t) 26987 26989 (face font-lock-doc-face fontified t) 26989 27007 (fontified t) 27007 27008 (prettify-symbols-end 27140 prettify-symbols-start 27139 composition (0 1 [32 65 57708]) fontified t) 27008 27009 (fontified t) 27009 27013 (face font-lock-builtin-face fontified t) 27013 27014 (fontified t) 27014 27015 (face font-lock-operator-face fontified t) 27015 27016 (fontified t) 27016 27020 (face font-lock-constant-face fontified t) 27020 27021 (fontified t) 27021 27022 (face font-lock-operator-face fontified t) 27022 27023 (fontified t) 27023 27027 (face font-lock-constant-face fontified t) 27027 27032 (fontified t) 27032 27034 (face font-lock-doc-face fontified t) 27034 27035 (face font-lock-doc-face syntax-table (15) fontified t) 27035 27114 (face font-lock-doc-face fontified t) 27114 27115 (face font-lock-doc-face syntax-table (15) fontified t) 27115 27117 (face font-lock-doc-face fontified t) 27117 27138 (fontified t) 27138 27139 (prettify-symbols-end 27271 prettify-symbols-start 27270 composition (0 1 [32 65 57708]) fontified t) 27139 27140 (fontified t) 27140 27144 (face font-lock-builtin-face fontified t) 27144 27145 (fontified t) 27145 27146 (face font-lock-operator-face fontified t) 27146 27147 (fontified t) 27147 27151 (face font-lock-constant-face fontified t) 27151 27152 (fontified t) 27152 27153 (face font-lock-operator-face fontified t) 27153 27154 (fontified t) 27154 27158 (face font-lock-constant-face fontified t) 27158 27163 (fontified t) 27163 27165 (face font-lock-doc-face fontified t) 27165 27166 (face font-lock-doc-face syntax-table (15) fontified t) 27166 27386 (face font-lock-doc-face fontified t) 27386 27387 (face font-lock-doc-face syntax-table (15) fontified t) 27387 27389 (face font-lock-doc-face fontified t) 27389 27409 (fontified t) 27409 27410 (prettify-symbols-end 27542 prettify-symbols-start 27541 composition ((1 32 65 57708)) fontified t) 27410 27411 (fontified t) 27411 27415 (face font-lock-builtin-face fontified t) 27415 27416 (fontified t) 27416 27417 (face font-lock-operator-face fontified t) 27417 27418 (fontified t) 27418 27422 (face font-lock-constant-face fontified t) 27422 27423 (fontified t) 27423 27424 (face font-lock-operator-face fontified t) 27424 27425 (fontified t) 27425 27429 (face font-lock-constant-face fontified t) 27429 27434 (fontified t) 27434 27436 (face font-lock-doc-face fontified t) 27436 27437 (face font-lock-doc-face syntax-table (15) fontified t) 27437 27653 (face font-lock-doc-face fontified t) 27653 27654 (face font-lock-doc-face syntax-table (15) fontified t) 27654 27656 (face font-lock-doc-face fontified t) 27656 27675 (fontified t) 27675 27676 (prettify-symbols-end 27808 prettify-symbols-start 27807 composition ((1 32 65 57708)) fontified t) 27676 27677 (fontified t) 27677 27681 (face font-lock-builtin-face fontified t) 27681 27682 (fontified t) 27682 27683 (face font-lock-operator-face fontified t) 27683 27684 (fontified t) 27684 27688 (face font-lock-constant-face fontified t) 27688 27689 (fontified t) 27689 27690 (face font-lock-operator-face fontified t) 27690 27691 (fontified t) 27691 27695 (face font-lock-constant-face fontified t) 27695 27700 (fontified t) 27700 27702 (face font-lock-doc-face fontified t) 27702 27703 (face font-lock-doc-face syntax-table (15) fontified t) 27703 27962 (face font-lock-doc-face fontified t) 27962 27963 (face font-lock-doc-face syntax-table (15) fontified t) 27963 27965 (face font-lock-doc-face fontified t) 27965 27970 (fontified t) 27970 27982 (face font-lock-variable-name-face fontified t) 27982 27983 (fontified t) 27983 27984 (face font-lock-operator-face fontified t) 27984 27995 (fontified t) 27995 27996 (face (rainbow-delimiters-depth-1-face) fontified t) 27996 28001 (fontified t) 28001 28002 (face font-lock-operator-face fontified t) 28002 28009 (face font-lock-string-face fontified t) 28009 28010 (face (rainbow-delimiters-depth-1-face) fontified t) 28010 28013 (fontified t) 28013 28018 (face font-lock-keyword-face fontified t) 28018 28019 (fontified t) 28019 28023 (face font-lock-type-face fontified t) 28023 28024 (face (rainbow-delimiters-depth-1-face) fontified t) 28024 28036 (fontified t) 28036 28037 (face (rainbow-delimiters-depth-1-face) fontified t) 28037 28038 (prettify-symbols-end 28170 prettify-symbols-start 28169 composition (0 1 [32 65 57708]) fontified t) 28038 28043 (fontified t) 28043 28045 (face font-lock-doc-face fontified t) 28045 28046 (face font-lock-doc-face syntax-table (15) fontified t) 28046 28088 (face font-lock-doc-face fontified t) 28088 28089 (face font-lock-doc-face syntax-table (15) fontified t) 28089 28091 (face font-lock-doc-face fontified t) 28091 28100 (fontified t) 28100 28101 (prettify-symbols-end 28233 prettify-symbols-start 28232 composition (0 1 [32 65 57708]) fontified t) 28101 28111 (fontified t) 28111 28112 (face (rainbow-delimiters-depth-1-face) fontified t) 28112 28134 (fontified t) 28134 28135 (face (rainbow-delimiters-depth-2-face) fontified t) 28135 28150 (fontified t) 28150 28151 (face font-lock-operator-face fontified t) 28151 28152 (face (rainbow-delimiters-depth-3-face) fontified t) 28152 28158 (face font-lock-string-face fontified t) 28158 28159 (face (rainbow-delimiters-depth-3-face) fontified t) 28159 28174 (fontified t) 28174 28175 (face font-lock-operator-face fontified t) 28175 28180 (face font-lock-constant-face fontified t) 28180 28181 (face (rainbow-delimiters-depth-2-face) fontified t) 28181 28182 (face (rainbow-delimiters-depth-1-face) fontified t) 28182 28187 (fontified t) 28187 28189 (face font-lock-string-face fontified t) 28189 28190 (face font-lock-string-face syntax-table (15) fontified t) 28190 28231 (face font-lock-string-face fontified t) 28231 28232 (face font-lock-string-face syntax-table (15) fontified t) 28232 28234 (face font-lock-string-face fontified t) 28234 28250 (fontified t) 28250 28251 (prettify-symbols-end 28383 prettify-symbols-start 28382 composition (0 1 [32 65 57708]) fontified t) 28251 28252 (fontified t) 28252 28255 (face font-lock-builtin-face fontified t) 28255 28256 (fontified t) 28256 28257 (face font-lock-operator-face fontified t) 28257 28258 (fontified t) 28258 28262 (face font-lock-constant-face fontified t) 28262 28263 (fontified t) 28263 28264 (face font-lock-operator-face fontified t) 28264 28265 (fontified t) 28265 28269 (face font-lock-constant-face fontified t) 28269 28274 (fontified t) 28274 28276 (face font-lock-doc-face fontified t) 28276 28277 (face font-lock-doc-face syntax-table (15) fontified t) 28277 28318 (face font-lock-doc-face fontified t) 28318 28319 (face font-lock-doc-face syntax-table (15) fontified t) 28319 28321 (face font-lock-doc-face fontified t) 28321 28337 (fontified t) 28337 28338 (prettify-symbols-end 28470 prettify-symbols-start 28469 composition (0 1 [32 65 57708]) fontified t) 28338 28339 (fontified t) 28339 28343 (face font-lock-builtin-face fontified t) 28343 28344 (face (rainbow-delimiters-depth-1-face) fontified t) 28344 28347 (face font-lock-builtin-face fontified t) 28347 28352 (fontified t) 28352 28353 (face (rainbow-delimiters-depth-1-face) fontified t) 28353 28358 (fontified t) 28358 28360 (face font-lock-string-face fontified t) 28360 28361 (face font-lock-string-face syntax-table (15) fontified t) 28361 28428 (face font-lock-string-face fontified t) 28428 28429 (face font-lock-string-face syntax-table (15) fontified t) 28429 28431 (face font-lock-string-face fontified t) 28431 28448 (fontified t) 28448 28449 (prettify-symbols-end 28581 prettify-symbols-start 28580 composition (0 1 [32 65 57708]) fontified t) 28449 28450 (fontified t) 28450 28454 (face font-lock-builtin-face fontified t) 28454 28455 (face (rainbow-delimiters-depth-1-face) fontified t) 28455 28458 (face font-lock-builtin-face fontified t) 28458 28463 (fontified t) 28463 28464 (face (rainbow-delimiters-depth-1-face) fontified t) 28464 28465 (fontified t) 28465 28466 (face font-lock-operator-face fontified t) 28466 28467 (fontified t) 28467 28471 (face font-lock-constant-face fontified t) 28471 28472 (fontified t) 28472 28473 (face font-lock-operator-face fontified t) 28473 28474 (fontified t) 28474 28478 (face font-lock-constant-face fontified t) 28478 28483 (fontified t) 28483 28485 (face font-lock-doc-face fontified t) 28485 28486 (face font-lock-doc-face syntax-table (15) fontified t) 28486 28635 (face font-lock-doc-face fontified t) 28635 28636 (face font-lock-doc-face syntax-table (15) fontified t) 28636 28638 (face font-lock-doc-face fontified t) 28638 28654 (fontified t) 28654 28655 (prettify-symbols-end 28787 prettify-symbols-start 28786 composition (0 1 [32 65 57708]) fontified t) 28655 28672 (fontified t) 28672 28673 (face font-lock-operator-face fontified t) 28673 28674 (fontified t) 28674 28678 (face font-lock-constant-face fontified t) 28678 28679 (fontified t) 28679 28680 (face font-lock-operator-face fontified t) 28680 28681 (fontified t) 28681 28685 (face font-lock-constant-face fontified t) 28685 28690 (fontified t) 28690 28692 (face font-lock-doc-face fontified t) 28692 28693 (face font-lock-doc-face syntax-table (15) fontified t) 28693 28730 (face font-lock-doc-face fontified t) 28730 28731 (face font-lock-doc-face syntax-table (15) fontified t) 28731 28733 (face font-lock-doc-face fontified t) 28733 28742 (fontified t) 28742 28743 (prettify-symbols-end 28875 prettify-symbols-start 28874 composition (0 1 [32 65 57708]) fontified t) 28743 28744 (fontified t) 28744 28748 (face font-lock-builtin-face fontified t) 28748 28749 (face (rainbow-delimiters-depth-1-face) fontified t) 28749 28752 (face font-lock-builtin-face fontified t) 28752 28757 (fontified t) 28757 28758 (face (rainbow-delimiters-depth-1-face) fontified t) 28758 28759 (fontified t) 28759 28760 (face font-lock-operator-face fontified t) 28760 28761 (fontified t) 28761 28765 (face font-lock-constant-face fontified t) 28765 28766 (fontified t) 28766 28767 (face font-lock-operator-face fontified t) 28767 28773 (fontified t) 28773 28774 (face (rainbow-delimiters-depth-1-face) fontified t) 28774 28779 (fontified t) 28779 28780 (face font-lock-operator-face fontified t) 28780 28787 (face font-lock-string-face fontified t) 28787 28796 (fontified t) 28796 28797 (face font-lock-operator-face fontified t) 28797 28801 (face font-lock-constant-face fontified t) 28801 28802 (face (rainbow-delimiters-depth-1-face) fontified t) 28802 28807 (fontified t) 28807 28809 (face font-lock-doc-face fontified t) 28809 28810 (face font-lock-doc-face syntax-table (15) fontified t) 28810 29037 (face font-lock-doc-face fontified t) 29037 29038 (face font-lock-doc-face syntax-table (15) fontified t) 29038 29040 (face font-lock-doc-face fontified t) 29040 29045 (fontified t) 29045 29057 (face font-lock-variable-name-face fontified t) 29057 29058 (fontified t) 29058 29059 (face font-lock-operator-face fontified t) 29059 29070 (fontified t) 29070 29071 (face (rainbow-delimiters-depth-1-face) fontified t) 29071 29076 (fontified t) 29076 29077 (face font-lock-operator-face fontified t) 29077 29084 (face font-lock-string-face fontified t) 29084 29085 (face (rainbow-delimiters-depth-1-face) fontified t)) . 132) (undo-tree-id0 . -3484) (undo-tree-id1 . -7754) (undo-tree-id2 . -29085) (t 26765 23376 312104 234000)) nil (26766 43722 623010 0) 0 nil] [nil nil ((42087 . 42088) (t 26765 23376 312104 234000)) ((#("n" 0 1 (ws-butler-chg chg fontified t)) . 42087)) (26766 23935 746852 0) 0 nil] [nil nil ((1 . 2) (t 26765 23376 312104 234000)) ((#(" +" 0 1 (ws-butler-chg chg fontified t)) . 1) (undo-tree-id0 . -1) (undo-tree-id1 . -1) (undo-tree-id2 . -1) (undo-tree-id3 . -1)) (26766 23908 526851 0) 0 nil]) +nil +nil +nil diff --git a/src/mcp/client/session.py b/src/mcp/client/session.py index 686d10f49..6a8c6d027 100644 --- a/src/mcp/client/session.py +++ b/src/mcp/client/session.py @@ -221,11 +221,13 @@ async def set_logging_level(self, level: types.LoggingLevel) -> types.EmptyResul types.EmptyResult, ) - async def list_resources(self, prefix: str | None = None, cursor: str | None = None) -> types.ListResourcesResult: + async def list_resources( + self, filters: types.ListFilters | None = None, cursor: str | None = None + ) -> types.ListResourcesResult: """Send a resources/list request.""" params = None - if cursor is not None or prefix is not None: - params = types.ListRequestParams(prefix=prefix, cursor=cursor) + if cursor is not None or filters is not None: + params = types.ListRequestParams(filters=filters, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListResourcesRequest( @@ -238,13 +240,13 @@ async def list_resources(self, prefix: str | None = None, cursor: str | None = N async def list_resource_templates( self, - prefix: str | None = None, + filters: types.ListFilters | None = None, cursor: str | None = None, ) -> types.ListResourceTemplatesResult: """Send a resources/templates/list request.""" params = None - if cursor is not None or prefix is not None: - params = types.ListRequestParams(prefix=prefix, cursor=cursor) + if cursor is not None or filters is not None: + params = types.ListRequestParams(filters=filters, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListResourceTemplatesRequest( @@ -342,11 +344,13 @@ async def _validate_tool_result(self, name: str, result: types.CallToolResult) - except SchemaError as e: raise RuntimeError(f"Invalid schema for tool {name}: {e}") - async def list_prompts(self, prefix: str | None = None, cursor: str | None = None) -> types.ListPromptsResult: + async def list_prompts( + self, filters: types.ListFilters | None = None, cursor: str | None = None + ) -> types.ListPromptsResult: """Send a prompts/list request.""" params = None - if cursor is not None or prefix is not None: - params = types.ListRequestParams(prefix=prefix, cursor=cursor) + if cursor is not None or filters is not None: + params = types.ListRequestParams(filters=filters, cursor=cursor) return await self.send_request( types.ClientRequest( types.ListPromptsRequest( @@ -394,11 +398,13 @@ async def complete( types.CompleteResult, ) - async def list_tools(self, prefix: str | None = None, cursor: str | None = None) -> types.ListToolsResult: + async def list_tools( + self, filters: types.ListFilters | None = None, cursor: str | None = None + ) -> types.ListToolsResult: """Send a tools/list request.""" params = None - if cursor is not None or prefix is not None: - params = types.ListRequestParams(prefix=prefix, cursor=cursor) + if cursor is not None or filters is not None: + params = types.ListRequestParams(filters=filters, cursor=cursor) result = await self.send_request( types.ClientRequest( types.ListToolsRequest( diff --git a/src/mcp/server/fastmcp/prompts/manager.py b/src/mcp/server/fastmcp/prompts/manager.py index e31291043..45ee7f264 100644 --- a/src/mcp/server/fastmcp/prompts/manager.py +++ b/src/mcp/server/fastmcp/prompts/manager.py @@ -3,7 +3,7 @@ from typing import Any from mcp.server.fastmcp.prompts.base import Message, Prompt -from mcp.server.fastmcp.uri_utils import filter_by_prefix, normalize_to_prompt_uri +from mcp.server.fastmcp.uri_utils import filter_by_uri_paths, normalize_to_prompt_uri from mcp.server.fastmcp.utilities.logging import get_logger logger = get_logger(__name__) @@ -25,11 +25,11 @@ def get_prompt(self, name: str) -> Prompt | None: uri = self._normalize_to_uri(name) return self._prompts.get(uri) - def list_prompts(self, prefix: str | None = None) -> list[Prompt]: - """List all registered prompts, optionally filtered by URI prefix.""" + def list_prompts(self, uri_paths: list[str] | None = None) -> list[Prompt]: + """List all registered prompts, optionally filtered by URI paths.""" prompts = list(self._prompts.values()) - prompts = filter_by_prefix(prompts, prefix, lambda p: p.uri) - logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) + prompts = filter_by_uri_paths(prompts, uri_paths, lambda p: p.uri) + logger.debug("Listing prompts", extra={"count": len(prompts), "uri_paths": uri_paths}) return prompts def add_prompt( diff --git a/src/mcp/server/fastmcp/prompts/prompt_manager.py b/src/mcp/server/fastmcp/prompts/prompt_manager.py index 1475856f8..772d00c22 100644 --- a/src/mcp/server/fastmcp/prompts/prompt_manager.py +++ b/src/mcp/server/fastmcp/prompts/prompt_manager.py @@ -1,7 +1,7 @@ """Prompt management functionality.""" from mcp.server.fastmcp.prompts.base import Prompt -from mcp.server.fastmcp.uri_utils import filter_by_prefix, normalize_to_prompt_uri +from mcp.server.fastmcp.uri_utils import filter_by_uri_paths, normalize_to_prompt_uri from mcp.server.fastmcp.utilities.logging import get_logger logger = get_logger(__name__) @@ -34,9 +34,9 @@ def get_prompt(self, name: str) -> Prompt | None: uri = self._normalize_to_uri(name) return self._prompts.get(uri) - def list_prompts(self, prefix: str | None = None) -> list[Prompt]: - """List all registered prompts, optionally filtered by URI prefix.""" + def list_prompts(self, uri_paths: list[str] | None = None) -> list[Prompt]: + """List all registered prompts, optionally filtered by URI paths.""" prompts = list(self._prompts.values()) - prompts = filter_by_prefix(prompts, prefix, lambda p: p.uri) - logger.debug("Listing prompts", extra={"count": len(prompts), "prefix": prefix}) + prompts = filter_by_uri_paths(prompts, uri_paths, lambda p: p.uri) + logger.debug("Listing prompts", extra={"count": len(prompts), "uri_paths": uri_paths}) return prompts diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index de4cc1fef..c30219717 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -7,7 +7,7 @@ from mcp.server.fastmcp.resources.base import Resource from mcp.server.fastmcp.resources.templates import ResourceTemplate -from mcp.server.fastmcp.uri_utils import filter_by_prefix +from mcp.server.fastmcp.uri_utils import filter_by_uri_paths from mcp.server.fastmcp.utilities.logging import get_logger logger = get_logger(__name__) @@ -87,20 +87,26 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: raise ValueError(f"Unknown resource: {uri}") - def list_resources(self, prefix: str | None = None) -> list[Resource]: - """List all registered resources, optionally filtered by URI prefix.""" + def list_resources(self, uri_paths: list[str] | None = None) -> list[Resource]: + """List all registered resources, optionally filtered by URI paths.""" resources = list(self._resources.values()) - resources = filter_by_prefix(resources, prefix, lambda r: r.uri) - logger.debug("Listing resources", extra={"count": len(resources), "prefix": prefix}) + resources = filter_by_uri_paths(resources, uri_paths, lambda r: r.uri) + logger.debug("Listing resources", extra={"count": len(resources), "uri_paths": uri_paths}) return resources - def list_templates(self, prefix: str | None = None) -> list[ResourceTemplate]: - """List all registered templates, optionally filtered by URI template prefix.""" + def list_templates(self, uri_paths: list[str] | None = None) -> list[ResourceTemplate]: + """List all registered templates, optionally filtered by URI paths.""" templates = list(self._templates.values()) - if prefix: - # Ensure prefix ends with / for proper path matching - if not prefix.endswith("/"): - prefix = prefix + "/" - templates = [t for t in templates if t.matches_prefix(prefix)] - logger.debug("Listing templates", extra={"count": len(templates), "prefix": prefix}) + if uri_paths: + filtered: list[ResourceTemplate] = [] + for template in templates: + for prefix in uri_paths: + # Ensure prefix ends with / for proper path matching + if not prefix.endswith("/"): + prefix = prefix + "/" + if template.matches_prefix(prefix): + filtered.append(template) + break + templates = filtered + logger.debug("Listing templates", extra={"count": len(templates), "uri_paths": uri_paths}) return templates diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 1d1625ef9..7e4dcb61a 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -268,11 +268,11 @@ def _setup_handlers(self) -> None: self._mcp_server.list_resource_templates()(self.list_resource_templates) async def list_tools(self, request: types.ListToolsRequest | None = None) -> list[MCPTool]: - """List all available tools, optionally filtered by prefix.""" - prefix = None - if request and request.params: - prefix = request.params.prefix - tools = self._tool_manager.list_tools(prefix=prefix) + """List all available tools, optionally filtered by URI paths.""" + uri_paths = None + if request and request.params and request.params.filters: + uri_paths = request.params.filters.uri_paths + tools = self._tool_manager.list_tools(uri_paths=uri_paths) return [ MCPTool( name=info.name, @@ -303,11 +303,11 @@ async def call_tool(self, name: str, arguments: dict[str, Any]) -> Sequence[Cont return await self._tool_manager.call_tool(name, arguments, context=context, convert_result=True) async def list_resources(self, request: types.ListResourcesRequest | None = None) -> list[MCPResource]: - """List all available resources, optionally filtered by prefix.""" - prefix = None - if request and request.params: - prefix = request.params.prefix - resources = self._resource_manager.list_resources(prefix=prefix) + """List all available resources, optionally filtered by URI paths.""" + uri_paths = None + if request and request.params and request.params.filters: + uri_paths = request.params.filters.uri_paths + resources = self._resource_manager.list_resources(uri_paths=uri_paths) return [ MCPResource( uri=resource.uri, @@ -322,11 +322,11 @@ async def list_resources(self, request: types.ListResourcesRequest | None = None async def list_resource_templates( self, request: types.ListResourceTemplatesRequest | None = None ) -> list[MCPResourceTemplate]: - """List all available resource templates, optionally filtered by prefix.""" - prefix = None - if request and request.params: - prefix = request.params.prefix - templates = self._resource_manager.list_templates(prefix=prefix) + """List all available resource templates, optionally filtered by URI paths.""" + uri_paths = None + if request and request.params and request.params.filters: + uri_paths = request.params.filters.uri_paths + templates = self._resource_manager.list_templates(uri_paths=uri_paths) return [ MCPResourceTemplate( uriTemplate=template.uri_template, @@ -970,11 +970,11 @@ def streamable_http_app(self) -> Starlette: ) async def list_prompts(self, request: types.ListPromptsRequest | None = None) -> list[MCPPrompt]: - """List all available prompts, optionally filtered by prefix.""" - prefix = None - if request and request.params: - prefix = request.params.prefix - prompts = self._prompt_manager.list_prompts(prefix=prefix) + """List all available prompts, optionally filtered by URI paths.""" + uri_paths = None + if request and request.params and request.params.filters: + uri_paths = request.params.filters.uri_paths + prompts = self._prompt_manager.list_prompts(uri_paths=uri_paths) return [ MCPPrompt( name=prompt.name, diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index f1c3d922c..6cd067731 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -5,7 +5,7 @@ from mcp.server.fastmcp.exceptions import ToolError from mcp.server.fastmcp.tools.base import Tool -from mcp.server.fastmcp.uri_utils import filter_by_prefix, normalize_to_tool_uri +from mcp.server.fastmcp.uri_utils import filter_by_uri_paths, normalize_to_tool_uri from mcp.server.fastmcp.utilities.logging import get_logger from mcp.shared.context import LifespanContextT, RequestT from mcp.types import ToolAnnotations @@ -44,11 +44,11 @@ def get_tool(self, name: str) -> Tool | None: uri = self._normalize_to_uri(name) return self._tools.get(uri) - def list_tools(self, prefix: str | None = None) -> list[Tool]: - """List all registered tools, optionally filtered by URI prefix.""" + def list_tools(self, uri_paths: list[str] | None = None) -> list[Tool]: + """List all registered tools, optionally filtered by URI paths.""" tools = list(self._tools.values()) - tools = filter_by_prefix(tools, prefix, lambda t: t.uri) - logger.debug("Listing tools", extra={"count": len(tools), "prefix": prefix}) + tools = filter_by_uri_paths(tools, uri_paths, lambda t: t.uri) + logger.debug("Listing tools", extra={"count": len(tools), "uri_paths": uri_paths}) return tools def add_tool( diff --git a/src/mcp/server/fastmcp/uri_utils.py b/src/mcp/server/fastmcp/uri_utils.py index 8405cbf84..69c018e9e 100644 --- a/src/mcp/server/fastmcp/uri_utils.py +++ b/src/mcp/server/fastmcp/uri_utils.py @@ -35,30 +35,35 @@ def normalize_to_prompt_uri(name_or_uri: str) -> str: return normalize_to_uri(name_or_uri, PROMPT_SCHEME) -def filter_by_prefix(items: list[T], prefix: str | None, uri_getter: Callable[[T], AnyUrl | str]) -> list[T]: - """Filter items by URI prefix. +def filter_by_uri_paths( + items: list[T], uri_paths: list[str] | None, uri_getter: Callable[[T], AnyUrl | str] +) -> list[T]: + """Filter items by multiple URI path prefixes. Args: items: List of items to filter - prefix: Optional prefix to filter by. If None, returns all items. + uri_paths: Optional list of URI path prefixes to filter by. If None or empty, returns all items. uri_getter: Function to extract URI from an item Returns: - Filtered list of items + Filtered list of items matching any of the provided prefixes """ - if not prefix: + if not uri_paths: return items - # Filter items where the URI starts with the prefix + # Filter items where the URI matches any of the prefixes filtered: list[T] = [] for item in items: uri = str(uri_getter(item)) - if uri.startswith(prefix): - # If prefix ends with a separator, we already have a proper boundary - if prefix.endswith(("/", "?", "#")): - filtered.append(item) - # Otherwise check if it's an exact match or if the next character is a separator - elif len(uri) == len(prefix) or uri[len(prefix)] in ("/", "?", "#"): - filtered.append(item) + for prefix in uri_paths: + if uri.startswith(prefix): + # If prefix ends with a separator, we already have a proper boundary + if prefix.endswith(("/", "?", "#")): + filtered.append(item) + break + # Otherwise check if it's an exact match or if the next character is a separator + elif len(uri) == len(prefix) or uri[len(prefix)] in ("/", "?", "#"): + filtered.append(item) + break return filtered diff --git a/src/mcp/types.py b/src/mcp/types.py index bfbc76df9..cfc219d94 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -60,9 +60,16 @@ class Meta(BaseModel): meta: Meta | None = Field(alias="_meta", default=None) +class ListFilters(BaseModel): + """Filters for list operations.""" + + uri_paths: list[str] | None = None + """Optional list of absolute URI path prefixes to filter results.""" + + class ListRequestParams(RequestParams): - prefix: str | None = None - """Optional prefix to filter results by URI.""" + filters: ListFilters | None = None + """Optional filters to apply to the list results.""" cursor: Cursor | None = None """ diff --git a/tests/server/fastmcp/prompts/test_manager.py b/tests/server/fastmcp/prompts/test_manager.py index 90bb317b1..1b1783418 100644 --- a/tests/server/fastmcp/prompts/test_manager.py +++ b/tests/server/fastmcp/prompts/test_manager.py @@ -104,38 +104,45 @@ def question_age() -> str: all_prompts = manager.list_prompts() assert len(all_prompts) == 4 - # Test prefix filtering - greeting prompts - greeting_prompts = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/") + # Test uri_paths filtering - greeting prompts + greeting_prompts = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/"]) assert len(greeting_prompts) == 2 assert all(str(p.uri).startswith(f"{PROMPT_SCHEME}/greeting/") for p in greeting_prompts) assert hello_prompt in greeting_prompts assert goodbye_prompt in greeting_prompts - # Test prefix filtering - question prompts - question_prompts = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/question/") + # Test uri_paths filtering - question prompts + question_prompts = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/question/"]) assert len(question_prompts) == 2 assert all(str(p.uri).startswith(f"{PROMPT_SCHEME}/question/") for p in question_prompts) assert name_prompt in question_prompts assert age_prompt in question_prompts # Test exact URI match - hello_prompts = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/hello") + hello_prompts = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/hello"]) assert len(hello_prompts) == 1 assert hello_prompts[0] == hello_prompt # Test partial prefix doesn't match - no_partial = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/h") + no_partial = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/h"]) assert len(no_partial) == 0 # Won't match because next char is 'e' not a separator # Test no matches - no_matches = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/nonexistent") + no_matches = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/nonexistent"]) assert len(no_matches) == 0 # Test with trailing slash - greeting_prompts_slash = manager.list_prompts(prefix=f"{PROMPT_SCHEME}/greeting/") + greeting_prompts_slash = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/"]) assert len(greeting_prompts_slash) == 2 assert greeting_prompts_slash == greeting_prompts + # Test multiple uri_paths + greeting_and_question = manager.list_prompts( + uri_paths=[f"{PROMPT_SCHEME}/greeting/", f"{PROMPT_SCHEME}/question/"] + ) + assert len(greeting_and_question) == 4 + assert all(p in greeting_and_question for p in all_prompts) + @pytest.mark.anyio async def test_render_prompt(self): """Test rendering a prompt.""" diff --git a/tests/server/fastmcp/resources/test_resource_manager.py b/tests/server/fastmcp/resources/test_resource_manager.py index c82ab465c..438c6a7e2 100644 --- a/tests/server/fastmcp/resources/test_resource_manager.py +++ b/tests/server/fastmcp/resources/test_resource_manager.py @@ -165,21 +165,26 @@ def test_list_resources_with_prefix(self, temp_file: Path): manager.add_resource(resource2) manager.add_resource(resource3) - # Test prefix filtering - data_resources = manager.list_resources(prefix="file:///data/") + # Test uri_paths filtering + data_resources = manager.list_resources(uri_paths=["file:///data/"]) assert len(data_resources) == 2 assert resource1 in data_resources assert resource2 in data_resources # More specific prefix - image_resources = manager.list_resources(prefix="file:///data/images/") + image_resources = manager.list_resources(uri_paths=["file:///data/images/"]) assert len(image_resources) == 1 assert resource1 in image_resources # No matches - no_matches = manager.list_resources(prefix="file:///nonexistent/") + no_matches = manager.list_resources(uri_paths=["file:///nonexistent/"]) assert len(no_matches) == 0 + # Multiple uri_paths + multi_resources = manager.list_resources(uri_paths=["file:///data/", "file:///other/"]) + assert len(multi_resources) == 3 + assert all(r in multi_resources for r in [resource1, resource2, resource3]) + def test_list_templates_with_prefix(self): """Test listing templates with prefix filtering.""" manager = ResourceManager() @@ -206,8 +211,8 @@ def product_func(product_id: str) -> str: all_templates = manager.list_templates() assert len(all_templates) == 3 - # Test prefix filtering - matches both user templates - user_templates = manager.list_templates(prefix="http://api.com/users/") + # Test uri_paths filtering - matches both user templates + user_templates = manager.list_templates(uri_paths=["http://api.com/users/"]) assert len(user_templates) == 2 assert template1 in user_templates assert template2 in user_templates @@ -215,20 +220,25 @@ def product_func(product_id: str) -> str: # Test partial materialization - only matches post template # The template users/{user_id} generates "users/123" not "users/123/" # But users/{user_id}/posts/{post_id} can generate "users/123/posts/456" - user_123_templates = manager.list_templates(prefix="http://api.com/users/123/") + user_123_templates = manager.list_templates(uri_paths=["http://api.com/users/123/"]) assert len(user_123_templates) == 1 assert template2 in user_123_templates # users/{user_id}/posts/{post_id} matches # Without trailing slash, it gets added automatically so only posts template matches - user_123_no_slash = manager.list_templates(prefix="http://api.com/users/123") + user_123_no_slash = manager.list_templates(uri_paths=["http://api.com/users/123"]) assert len(user_123_no_slash) == 1 assert template2 in user_123_no_slash # Only posts template has path after users/123/ # Test product prefix - product_templates = manager.list_templates(prefix="http://api.com/products/") + product_templates = manager.list_templates(uri_paths=["http://api.com/products/"]) assert len(product_templates) == 1 assert template3 in product_templates # No matches - no_matches = manager.list_templates(prefix="http://api.com/orders/") + no_matches = manager.list_templates(uri_paths=["http://api.com/orders/"]) assert len(no_matches) == 0 + + # Multiple uri_paths + users_and_products = manager.list_templates(uri_paths=["http://api.com/users/", "http://api.com/products/"]) + assert len(users_and_products) == 3 + assert all(t in users_and_products for t in all_templates) diff --git a/tests/server/fastmcp/test_tool_manager.py b/tests/server/fastmcp/test_tool_manager.py index c4041bc24..29a0a35e4 100644 --- a/tests/server/fastmcp/test_tool_manager.py +++ b/tests/server/fastmcp/test_tool_manager.py @@ -219,38 +219,43 @@ def string_upper(text: str) -> str: all_tools = manager.list_tools() assert len(all_tools) == 4 - # Test prefix filtering - math tools - math_tools = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/") + # Test uri_paths filtering - math tools + math_tools = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/"]) assert len(math_tools) == 2 assert all(str(t.uri).startswith(f"{TOOL_SCHEME}/math/") for t in math_tools) assert math_add_tool in math_tools assert math_multiply_tool in math_tools - # Test prefix filtering - string tools - string_tools = manager.list_tools(prefix=f"{TOOL_SCHEME}/string/") + # Test uri_paths filtering - string tools + string_tools = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/string/"]) assert len(string_tools) == 2 assert all(str(t.uri).startswith(f"{TOOL_SCHEME}/string/") for t in string_tools) assert string_concat_tool in string_tools assert string_upper_tool in string_tools # Test exact URI match - add_tools = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/add") + add_tools = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/add"]) assert len(add_tools) == 1 assert add_tools[0] == math_add_tool # Test partial prefix doesn't match - no_partial = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/a") + no_partial = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/a"]) assert len(no_partial) == 0 # Won't match because next char is 'd' not a separator # Test no matches - no_matches = manager.list_tools(prefix=f"{TOOL_SCHEME}/nonexistent") + no_matches = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/nonexistent"]) assert len(no_matches) == 0 # Test with trailing slash - math_tools_slash = manager.list_tools(prefix=f"{TOOL_SCHEME}/math/") + math_tools_slash = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/"]) assert len(math_tools_slash) == 2 assert math_tools_slash == math_tools + # Test multiple uri_paths + math_and_string = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/", f"{TOOL_SCHEME}/string/"]) + assert len(math_and_string) == 4 + assert all(t in math_and_string for t in all_tools) + class TestCallTools: @pytest.mark.anyio diff --git a/tests/server/fastmcp/test_uri_utils.py b/tests/server/fastmcp/test_uri_utils.py index c6ebbac5c..27329225a 100644 --- a/tests/server/fastmcp/test_uri_utils.py +++ b/tests/server/fastmcp/test_uri_utils.py @@ -1,7 +1,7 @@ """Tests for URI utility functions.""" from mcp.server.fastmcp.uri_utils import ( - filter_by_prefix, + filter_by_uri_paths, normalize_to_prompt_uri, normalize_to_tool_uri, normalize_to_uri, @@ -79,102 +79,117 @@ def test_normalize_prompt_with_path(self): assert result == f"{PROMPT_SCHEME}/templates/greeting" -class TestFilterByPrefix: - """Test the prefix filtering function.""" +class TestFilterByUriPaths: + """Test the URI paths filtering function.""" - def test_filter_no_prefix(self): - """Test that no prefix returns all items.""" + def test_filter_no_paths(self): + """Test that no paths returns all items.""" items = ["item1", "item2", "item3"] - result = filter_by_prefix(items, None, lambda x: x) + result = filter_by_uri_paths(items, None, lambda x: x) assert result == items - def test_filter_with_prefix(self): - """Test filtering with a prefix.""" + def test_filter_empty_paths(self): + """Test that empty paths list returns all items.""" + items = ["item1", "item2", "item3"] + result = filter_by_uri_paths(items, [], lambda x: x) + assert result == items + + def test_filter_single_path(self): + """Test filtering with a single path.""" items = [f"{TOOL_SCHEME}/math/add", f"{TOOL_SCHEME}/math/subtract", f"{TOOL_SCHEME}/string/concat"] - result = filter_by_prefix(items, f"{TOOL_SCHEME}/math", lambda x: x) + result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math"], lambda x: x) assert len(result) == 2 assert f"{TOOL_SCHEME}/math/add" in result assert f"{TOOL_SCHEME}/math/subtract" in result - def test_filter_prefix_without_slash(self): - """Test that prefix without trailing slash only matches at boundaries.""" + def test_filter_multiple_paths(self): + """Test filtering with multiple paths.""" items = [ f"{TOOL_SCHEME}/math/add", f"{TOOL_SCHEME}/math/subtract", f"{TOOL_SCHEME}/string/concat", - f"{TOOL_SCHEME}/mathematic", + f"{PROMPT_SCHEME}/greet/hello", ] - result = filter_by_prefix(items, f"{TOOL_SCHEME}/math", lambda x: x) - assert len(result) == 2 # Matches because next char is '/' + result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math", f"{PROMPT_SCHEME}/greet"], lambda x: x) + assert len(result) == 3 assert f"{TOOL_SCHEME}/math/add" in result assert f"{TOOL_SCHEME}/math/subtract" in result - assert f"{TOOL_SCHEME}/mathematic" not in result # Doesn't match because next char is 'e' + assert f"{PROMPT_SCHEME}/greet/hello" in result + assert f"{TOOL_SCHEME}/string/concat" not in result - # With trailing slash also matches - result_with_slash = filter_by_prefix(items, f"{TOOL_SCHEME}/math/", lambda x: x) - assert len(result_with_slash) == 2 - assert result_with_slash == result + def test_filter_paths_without_slash(self): + """Test that paths without trailing slash only match at boundaries.""" + items = [ + f"{TOOL_SCHEME}/math/add", + f"{TOOL_SCHEME}/math/subtract", + f"{TOOL_SCHEME}/string/concat", + f"{TOOL_SCHEME}/mathematic", + ] + result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math", f"{TOOL_SCHEME}/string"], lambda x: x) + assert len(result) == 3 + assert f"{TOOL_SCHEME}/math/add" in result + assert f"{TOOL_SCHEME}/math/subtract" in result + assert f"{TOOL_SCHEME}/string/concat" in result + assert f"{TOOL_SCHEME}/mathematic" not in result - def test_filter_with_trailing_slash(self): - """Test filtering when prefix already has trailing slash.""" - items = [f"{PROMPT_SCHEME}/greet/hello", f"{PROMPT_SCHEME}/greet/goodbye", f"{PROMPT_SCHEME}/chat/start"] - result = filter_by_prefix(items, f"{PROMPT_SCHEME}/greet/", lambda x: x) - assert len(result) == 2 - assert f"{PROMPT_SCHEME}/greet/hello" in result - assert f"{PROMPT_SCHEME}/greet/goodbye" in result + def test_filter_with_trailing_slashes(self): + """Test filtering when paths have trailing slashes.""" + items = [ + f"{PROMPT_SCHEME}/greet/hello", + f"{PROMPT_SCHEME}/greet/goodbye", + f"{PROMPT_SCHEME}/chat/start", + ] + result = filter_by_uri_paths(items, [f"{PROMPT_SCHEME}/greet/", f"{PROMPT_SCHEME}/chat/"], lambda x: x) + assert len(result) == 3 + assert all(item in result for item in items) - def test_filter_empty_list(self): - """Test filtering empty list.""" - items = [] - result = filter_by_prefix(items, "any://prefix", lambda x: x) - assert result == [] + def test_filter_overlapping_paths(self): + """Test filtering with overlapping paths.""" + items = [ + f"{TOOL_SCHEME}/math", + f"{TOOL_SCHEME}/math/add", + f"{TOOL_SCHEME}/math/advanced/multiply", + ] + result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math", f"{TOOL_SCHEME}/math/advanced"], lambda x: x) + assert len(result) == 3 # All items match + assert all(item in result for item in items) def test_filter_no_matches(self): - """Test filtering when no items match.""" + """Test filtering when no items match any path.""" items = [f"{TOOL_SCHEME}/math/add", f"{TOOL_SCHEME}/math/subtract"] - result = filter_by_prefix(items, f"{TOOL_SCHEME}/string", lambda x: x) + result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/string", f"{PROMPT_SCHEME}/greet"], lambda x: x) assert result == [] def test_filter_with_objects(self): """Test filtering objects using a URI getter function.""" - class MockTool: + class MockResource: def __init__(self, uri): self.uri = uri - tools = [ - MockTool(f"{TOOL_SCHEME}/math/add"), - MockTool(f"{TOOL_SCHEME}/math/multiply"), - MockTool(f"{TOOL_SCHEME}/string/concat"), + resources = [ + MockResource(f"{TOOL_SCHEME}/math/add"), + MockResource(f"{TOOL_SCHEME}/string/concat"), + MockResource(f"{PROMPT_SCHEME}/greet/hello"), ] - result = filter_by_prefix(tools, f"{TOOL_SCHEME}/math", lambda t: t.uri) + result = filter_by_uri_paths(resources, [f"{TOOL_SCHEME}/math", f"{PROMPT_SCHEME}/greet"], lambda r: r.uri) assert len(result) == 2 assert result[0].uri == f"{TOOL_SCHEME}/math/add" - assert result[1].uri == f"{TOOL_SCHEME}/math/multiply" + assert result[1].uri == f"{PROMPT_SCHEME}/greet/hello" def test_filter_case_sensitive(self): """Test that filtering is case sensitive.""" items = [f"{TOOL_SCHEME}/Math/add", f"{TOOL_SCHEME}/math/add"] - result = filter_by_prefix(items, f"{TOOL_SCHEME}/math", lambda x: x) + result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math"], lambda x: x) assert len(result) == 1 assert f"{TOOL_SCHEME}/math/add" in result - def test_filter_exact_prefix_match(self): - """Test that exact prefix matches work correctly.""" + def test_filter_exact_path_match(self): + """Test that exact path matches work correctly.""" items = [f"{TOOL_SCHEME}/test", f"{TOOL_SCHEME}/test/sub", f"{TOOL_SCHEME}/testing"] - result = filter_by_prefix(items, f"{TOOL_SCHEME}/test", lambda x: x) - # Should match "tool:/test" (exact) and "tool:/test/sub" but not "tool:/testing" + result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/test"], lambda x: x) assert len(result) == 2 assert f"{TOOL_SCHEME}/test" in result assert f"{TOOL_SCHEME}/test/sub" in result assert f"{TOOL_SCHEME}/testing" not in result - - def test_filter_root_prefix(self): - """Test filtering with just the scheme as prefix.""" - items = [f"{TOOL_SCHEME}/add", f"{TOOL_SCHEME}/subtract", f"{PROMPT_SCHEME}/greet"] - result = filter_by_prefix(items, f"{TOOL_SCHEME}/", lambda x: x) - assert len(result) == 2 - assert f"{TOOL_SCHEME}/add" in result - assert f"{TOOL_SCHEME}/subtract" in result - assert f"{PROMPT_SCHEME}/greet" not in result diff --git a/types_protocol_changes.md b/types_protocol_changes.md new file mode 100644 index 000000000..18bba3574 --- /dev/null +++ b/types_protocol_changes.md @@ -0,0 +1,67 @@ +# Protocol Changes in types.py + +## URI Standardization + +### Added URI schemes +```python +MCP_SCHEME = "mcp" +TOOL_SCHEME = "mcp://tools" +PROMPT_SCHEME = "mcp://prompts" +``` + +## Request/Response Changes + +### Renamed pagination to list-based naming +```python +# Before +class PaginatedRequestParams(RequestParams): + cursor: Cursor | None = None + +class PaginatedRequest(Request[PaginatedRequestParams | None, MethodT]) +class PaginatedResult(Result) + +# After +class ListRequestParams(RequestParams): + prefix: str | None = None # NEW: prefix filtering + cursor: Cursor | None = None + +class ListRequest(Request[ListRequestParams | None, MethodT]) +class ListResult(Result) +``` + +## Tool Protocol Changes + +### Tool now includes URI +```python +class Tool(BaseMetadata): + uri: AnyUrl | None = None # NEW: auto-generated as mcp://tools/{name} + description: str | None = None + inputSchema: dict[str, Any] +``` + +## Prompt Protocol Changes + +### Prompt now includes URI +```python +class Prompt(BaseMetadata): + uri: AnyUrl | None = None # NEW: auto-generated as mcp://prompts/{name} + description: str | None = None + arguments: list[PromptArgument] | None = None +``` + +## Resource Validation + +### Resources cannot use tool/prompt URI schemes +```python +@model_validator(mode="after") +def validate_uri_scheme(self) -> "Resource": + # Prevents resources from using mcp://tools or mcp://prompts +``` + +## List Methods Update + +All list requests now support prefix filtering: +- `ListResourcesRequest` +- `ListToolsRequest` +- `ListPromptsRequest` +- `ListResourceTemplatesRequest` \ No newline at end of file From 9eea4099b6cd00ba493ef6cb4430b5a7884e794d Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sun, 3 Aug 2025 16:06:37 -0700 Subject: [PATCH 14/15] feat: Use AnyUrl type for URI fields and update managers - Change Tool and Prompt classes to use AnyUrl for uri field - Update all manager get/call methods to accept AnyUrl | str - Add method overloads for better type hints - Update tests to use AnyUrl objects - Update filter_by_uri_paths to use Sequence for covariance --- src/mcp/.types.py.~undo-tree~ | 881 ------------------ src/mcp/server/fastmcp/prompts/base.py | 6 +- src/mcp/server/fastmcp/prompts/manager.py | 45 +- .../server/fastmcp/prompts/prompt_manager.py | 7 +- .../fastmcp/resources/resource_manager.py | 14 +- src/mcp/server/fastmcp/tools/base.py | 6 +- src/mcp/server/fastmcp/tools/tool_manager.py | 53 +- src/mcp/server/fastmcp/uri_utils.py | 33 +- src/mcp/types.py | 2 +- tests/server/fastmcp/prompts/test_manager.py | 27 +- .../resources/test_resource_manager.py | 22 +- tests/server/fastmcp/test_tool_manager.py | 28 +- tests/server/fastmcp/test_uri_utils.py | 137 +-- types_protocol_changes.md | 10 +- 14 files changed, 240 insertions(+), 1031 deletions(-) delete mode 100644 src/mcp/.types.py.~undo-tree~ diff --git a/src/mcp/.types.py.~undo-tree~ b/src/mcp/.types.py.~undo-tree~ deleted file mode 100644 index 9e447dcb4..000000000 --- a/src/mcp/.types.py.~undo-tree~ +++ /dev/null @@ -1,881 +0,0 @@ -(undo-tree-save-format-version . 1) -"7c2534cb5695c3932bb3680b0e4064ac87d139ad" -[nil nil nil nil (26766 23935 767928 0) 0 nil] -([nil current ((132 . 30686) (#("BaseModel, ConfigDict, Field, FileUrl, RootModel, model_validator -from pydantic.networks import AnyUrl, UrlConstraints -from typing_extensions import deprecated - -\"\"\" -Model Context Protocol bindings for Python - -These bindings were generated from https://github.com/modelcontextprotocol/specification, -using Claude, with a prompt something like the following: - -Generate idiomatic Python bindings for this schema for MCP, or the \"Model Context -Protocol.\" The schema is defined in TypeScript, but there's also a JSON Schema version -for reference. - -* For the bindings, let's use Pydantic V2 models. -* Each model should allow extra fields everywhere, by specifying `model_config = - ConfigDict(extra='allow')`. Do this in every case, instead of a custom base class. -* Union types should be represented with a Pydantic `RootModel`. -* Define additional model classes instead of using dictionaries. Do this even if they're - not separate types in the schema. -\"\"\" - -LATEST_PROTOCOL_VERSION = \"2025-06-18\" - -\"\"\" -The default negotiated version of the Model Context Protocol when no version is specified. -We need this to satisfy the MCP specification, which requires the server to assume a -specific version if none is provided by the client. See section \"Protocol Version Header\" at -https://modelcontextprotocol.io/specification -\"\"\" -DEFAULT_NEGOTIATED_VERSION = \"2025-03-26\" - -ProgressToken = str | int -Cursor = str -Role = Literal[\"user\", \"assistant\"] -RequestId = Annotated[int, Field(strict=True)] | str -AnyFunction: TypeAlias = Callable[..., Any] - - -class RequestParams(BaseModel): - class Meta(BaseModel): - progressToken: ProgressToken | None = None - \"\"\" - If specified, the caller requests out-of-band progress notifications for - this request (as represented by notifications/progress). The value of this - parameter is an opaque token that will be attached to any subsequent - notifications. The receiver is not obligated to provide these notifications. - \"\"\" - - model_config = ConfigDict(extra=\"allow\") - - meta: Meta | None = Field(alias=\"_meta\", default=None) - - -class ListRequestParams(RequestParams): - prefix: str | None = None - \"\"\"Optional prefix to filter results by URI.\"\"\" - - cursor: Cursor | None = None - \"\"\" - An opaque token representing the current pagination position. - If provided, the server should return results starting after this cursor. - \"\"\" - - -class NotificationParams(BaseModel): - class Meta(BaseModel): - model_config = ConfigDict(extra=\"allow\") - - meta: Meta | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - - -RequestParamsT = TypeVar(\"RequestParamsT\", bound=RequestParams | dict[str, Any] | None) -NotificationParamsT = TypeVar(\"NotificationParamsT\", bound=NotificationParams | dict[str, Any] | None) -MethodT = TypeVar(\"MethodT\", bound=str) - - -class Request(BaseModel, Generic[RequestParamsT, MethodT]): - \"\"\"Base class for JSON-RPC requests.\"\"\" - - method: MethodT - params: RequestParamsT - model_config = ConfigDict(extra=\"allow\") - - -class ListRequest(Request[ListRequestParams | None, MethodT], Generic[MethodT]): - \"\"\"Base class for list requests, - matching the schema's ListRequest interface.\"\"\" - - params: ListRequestParams | None = None - - -class Notification(BaseModel, Generic[NotificationParamsT, MethodT]): - \"\"\"Base class for JSON-RPC notifications.\"\"\" - - method: MethodT - params: NotificationParamsT - model_config = ConfigDict(extra=\"allow\") - - -class Result(BaseModel): - \"\"\"Base class for JSON-RPC results.\"\"\" - - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ListResult(Result): - nextCursor: Cursor | None = None - \"\"\" - An opaque token representing the pagination position after the last returned result. - If present, there may be more results available. - \"\"\" - - -class JSONRPCRequest(Request[dict[str, Any] | None, str]): - \"\"\"A request that expects a response.\"\"\" - - jsonrpc: Literal[\"2.0\"] - id: RequestId - method: str - params: dict[str, Any] | None = None - - -class JSONRPCNotification(Notification[dict[str, Any] | None, str]): - \"\"\"A notification which does not expect a response.\"\"\" - - jsonrpc: Literal[\"2.0\"] - params: dict[str, Any] | None = None - - -class JSONRPCResponse(BaseModel): - \"\"\"A successful (non-error) response to a request.\"\"\" - - jsonrpc: Literal[\"2.0\"] - id: RequestId - result: dict[str, Any] - model_config = ConfigDict(extra=\"allow\") - - -# SDK error codes -CONNECTION_CLOSED = -32000 -# REQUEST_TIMEOUT = -32001 # the typescript sdk uses this - -# Standard JSON-RPC error codes -PARSE_ERROR = -32700 -INVALID_REQUEST = -32600 -METHOD_NOT_FOUND = -32601 -INVALID_PARAMS = -32602 -INTERNAL_ERROR = -32603 - - -class ErrorData(BaseModel): - \"\"\"Error information for JSON-RPC error responses.\"\"\" - - code: int - \"\"\"The error type that occurred.\"\"\" - - message: str - \"\"\" - A short description of the error. The message SHOULD be limited to a concise single - sentence. - \"\"\" - - data: Any | None = None - \"\"\" - Additional information about the error. The value of this member is defined by the - sender (e.g. detailed error information, nested errors etc.). - \"\"\" - - model_config = ConfigDict(extra=\"allow\") - - -class JSONRPCError(BaseModel): - \"\"\"A response to a request that indicates an error occurred.\"\"\" - - jsonrpc: Literal[\"2.0\"] - id: str | int - error: ErrorData - model_config = ConfigDict(extra=\"allow\") - - -class JSONRPCMessage(RootModel[JSONRPCRequest | JSONRPCNotification | JSONRPCResponse | JSONRPCError]): - pass - - -class EmptyResult(Result): - \"\"\"A response that indicates success but carries no data.\"\"\" - - -class BaseMetadata(BaseModel): - \"\"\"Base class for entities with name and optional title fields.\"\"\" - - name: str - \"\"\"The programmatic name of the entity.\"\"\" - - title: str | None = None - \"\"\" - Intended for UI and end-user contexts — optimized to be human-readable and easily understood, - even by those unfamiliar with domain-specific terminology. - - If not provided, the name should be used for display (except for Tool, - where `annotations.title` should be given precedence over using `name`, - if present). - \"\"\" - - -class Implementation(BaseMetadata): - \"\"\"Describes the name and version of an MCP implementation.\"\"\" - - version: str - model_config = ConfigDict(extra=\"allow\") - - -class RootsCapability(BaseModel): - \"\"\"Capability for root operations.\"\"\" - - listChanged: bool | None = None - \"\"\"Whether the client supports notifications for changes to the roots list.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class SamplingCapability(BaseModel): - \"\"\"Capability for sampling operations.\"\"\" - - model_config = ConfigDict(extra=\"allow\") - - -class ElicitationCapability(BaseModel): - \"\"\"Capability for elicitation operations.\"\"\" - - model_config = ConfigDict(extra=\"allow\") - - -class ClientCapabilities(BaseModel): - \"\"\"Capabilities a client may support.\"\"\" - - experimental: dict[str, dict[str, Any]] | None = None - \"\"\"Experimental, non-standard capabilities that the client supports.\"\"\" - sampling: SamplingCapability | None = None - \"\"\"Present if the client supports sampling from an LLM.\"\"\" - elicitation: ElicitationCapability | None = None - \"\"\"Present if the client supports elicitation from the user.\"\"\" - roots: RootsCapability | None = None - \"\"\"Present if the client supports listing roots.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class PromptsCapability(BaseModel): - \"\"\"Capability for prompts operations.\"\"\" - - listChanged: bool | None = None - \"\"\"Whether this server supports notifications for changes to the prompt list.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ResourcesCapability(BaseModel): - \"\"\"Capability for resources operations.\"\"\" - - subscribe: bool | None = None - \"\"\"Whether this server supports subscribing to resource updates.\"\"\" - listChanged: bool | None = None - \"\"\"Whether this server supports notifications for changes to the resource list.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ToolsCapability(BaseModel): - \"\"\"Capability for tools operations.\"\"\" - - listChanged: bool | None = None - \"\"\"Whether this server supports notifications for changes to the tool list.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class LoggingCapability(BaseModel): - \"\"\"Capability for logging operations.\"\"\" - - model_config = ConfigDict(extra=\"allow\") - - -class CompletionsCapability(BaseModel): - \"\"\"Capability for completions operations.\"\"\" - - model_config = ConfigDict(extra=\"allow\") - - -class ServerCapabilities(BaseModel): - \"\"\"Capabilities that a server may support.\"\"\" - - experimental: dict[str, dict[str, Any]] | None = None - \"\"\"Experimental, non-standard capabilities that the server supports.\"\"\" - logging: LoggingCapability | None = None - \"\"\"Present if the server supports sending log messages to the client.\"\"\" - prompts: PromptsCapability | None = None - \"\"\"Present if the server offers any prompt templates.\"\"\" - resources: ResourcesCapability | None = None - \"\"\"Present if the server offers any resources to read.\"\"\" - tools: ToolsCapability | None = None - \"\"\"Present if the server offers any tools to call.\"\"\" - completions: CompletionsCapability | None = None - \"\"\"Present if the server offers autocompletion suggestions for prompts and resources.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class InitializeRequestParams(RequestParams): - \"\"\"Parameters for the initialize request.\"\"\" - - protocolVersion: str | int - \"\"\"The latest version of the Model Context Protocol that the client supports.\"\"\" - capabilities: ClientCapabilities - clientInfo: Implementation - model_config = ConfigDict(extra=\"allow\") - - -class InitializeRequest(Request[InitializeRequestParams, Literal[\"initialize\"]]): - \"\"\" - This request is sent from the client to the server when it first connects, asking it - to begin initialization. - \"\"\" - - method: Literal[\"initialize\"] - params: InitializeRequestParams - - -class InitializeResult(Result): - \"\"\"After receiving an initialize request from the client, the server sends this.\"\"\" - - protocolVersion: str | int - \"\"\"The version of the Model Context Protocol that the server wants to use.\"\"\" - capabilities: ServerCapabilities - serverInfo: Implementation - instructions: str | None = None - \"\"\"Instructions describing how to use the server and its features.\"\"\" - - -class InitializedNotification(Notification[NotificationParams | None, Literal[\"notifications/initialized\"]]): - \"\"\" - This notification is sent from the client to the server after initialization has - finished. - \"\"\" - - method: Literal[\"notifications/initialized\"] - params: NotificationParams | None = None - - -class PingRequest(Request[RequestParams | None, Literal[\"ping\"]]): - \"\"\" - A ping, issued by either the server or the client, to check that the other party is - still alive. - \"\"\" - - method: Literal[\"ping\"] - params: RequestParams | None = None - - -class ProgressNotificationParams(NotificationParams): - \"\"\"Parameters for progress notifications.\"\"\" - - progressToken: ProgressToken - \"\"\" - The progress token which was given in the initial request, used to associate this - notification with the request that is proceeding. - \"\"\" - progress: float - \"\"\" - The progress thus far. This should increase every time progress is made, even if the - total is unknown. - \"\"\" - total: float | None = None - \"\"\"Total number of items to process (or total progress required), if known.\"\"\" - message: str | None = None - \"\"\" - Message related to progress. This should provide relevant human readable - progress information. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ProgressNotification(Notification[ProgressNotificationParams, Literal[\"notifications/progress\"]]): - \"\"\" - An out-of-band notification used to inform the receiver of a progress update for a - long-running request. - \"\"\" - - method: Literal[\"notifications/progress\"] - params: ProgressNotificationParams - - -class ListResourcesRequest(ListRequest[Literal[\"resources/list\"]]): - \"\"\"Sent from the client to request a list of resources the server has.\"\"\" - - method: Literal[\"resources/list\"] - - -class Annotations(BaseModel): - audience: list[Role] | None = None - priority: Annotated[float, Field(ge=0.0, le=1.0)] | None = None - model_config = ConfigDict(extra=\"allow\") - - -class Resource(BaseMetadata): - \"\"\"A known resource that the server is capable of reading.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] - \"\"\"The URI of this resource.\"\"\" - description: str | None = None - \"\"\"A description of what this resource represents.\"\"\" - mimeType: str | None = None - \"\"\"The MIME type of this resource, if known.\"\"\" - size: int | None = None - \"\"\" - The size of the raw resource content, in bytes (i.e., before base64 encoding - or any tokenization), if known. - - This can be used by Hosts to display file sizes and estimate context window usage. - \"\"\" - annotations: Annotations | None = None - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - @model_validator(mode=\"after\") - def validate_uri_scheme(self) -> \"Resource\": - \"\"\"Ensure resource URI doesn't use reserved schemes.\"\"\" - uri_str = str(self.uri) - if uri_str.startswith((\"tool://\", \"prompt://\")): - raise ValueError(f\"Resource URI cannot use reserved schemes 'tool://' or 'prompt://', got: {self.uri}\") - return self - - -class ResourceTemplate(BaseMetadata): - \"\"\"A template description for resources available on the server.\"\"\" - - uriTemplate: str - \"\"\" - A URI template (according to RFC 6570) that can be used to construct resource - URIs. - \"\"\" - description: str | None = None - \"\"\"A human-readable description of what this template is for.\"\"\" - mimeType: str | None = None - \"\"\" - The MIME type for all resources that match this template. This should only be - included if all resources matching this template have the same type. - \"\"\" - annotations: Annotations | None = None - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ListResourcesResult(ListResult): - \"\"\"The server's response to a resources/list request from the client.\"\"\" - - resources: list[Resource] - - -class ListResourceTemplatesRequest(ListRequest[Literal[\"resources/templates/list\"]]): - \"\"\"Sent from the client to request a list of resource templates the server has.\"\"\" - - method: Literal[\"resources/templates/list\"] - - -class ListResourceTemplatesResult(ListResult): - \"\"\"The server's response to a resources/templates/list request from the client.\"\"\" - - resourceTemplates: list[ResourceTemplate] - - -class ReadResourceRequestParams(RequestParams): - \"\"\"Parameters for reading a resource.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] - \"\"\" - The URI of the resource to read. The URI can use any protocol; it is up to the - server how to interpret it. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ReadResourceRequest(Request[ReadResourceRequestParams, Literal[\"resources/read\"]]): - \"\"\"Sent from the client to the server, to read a specific resource URI.\"\"\" - - method: Literal[\"resources/read\"] - params: ReadResourceRequestParams - - -class ResourceContents(BaseModel): - \"\"\"The contents of a specific resource or sub-resource.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] - \"\"\"The URI of this resource.\"\"\" - mimeType: str | None = None - \"\"\"The MIME type of this resource, if known.\"\"\" - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class TextResourceContents(ResourceContents): - \"\"\"Text contents of a resource.\"\"\" - - text: str - \"\"\" - The text of the item. This must only be set if the item can actually be represented - as text (not binary data). - \"\"\" - - -class BlobResourceContents(ResourceContents): - \"\"\"Binary contents of a resource.\"\"\" - - blob: str - \"\"\"A base64-encoded string representing the binary data of the item.\"\"\" - - -class ReadResourceResult(Result): - \"\"\"The server's response to a resources/read request from the client.\"\"\" - - contents: list[TextResourceContents | BlobResourceContents] - - -class ResourceListChangedNotification( - Notification[NotificationParams | None, Literal[\"notifications/resources/list_changed\"]] -): - \"\"\" - An optional notification from the server to the client, informing it that the list - of resources it can read from has changed. - \"\"\" - - method: Literal[\"notifications/resources/list_changed\"] - params: NotificationParams | None = None - - -class SubscribeRequestParams(RequestParams): - \"\"\"Parameters for subscribing to a resource.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] - \"\"\" - The URI of the resource to subscribe to. The URI can use any protocol; it is up to - the server how to interpret it. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class SubscribeRequest(Request[SubscribeRequestParams, Literal[\"resources/subscribe\"]]): - \"\"\" - Sent from the client to request resources/updated notifications from the server - whenever a particular resource changes. - \"\"\" - - method: Literal[\"resources/subscribe\"] - params: SubscribeRequestParams - - -class UnsubscribeRequestParams(RequestParams): - \"\"\"Parameters for unsubscribing from a resource.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] - \"\"\"The URI of the resource to unsubscribe from.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class UnsubscribeRequest(Request[UnsubscribeRequestParams, Literal[\"resources/unsubscribe\"]]): - \"\"\" - Sent from the client to request cancellation of resources/updated notifications from - the server. - \"\"\" - - method: Literal[\"resources/unsubscribe\"] - params: UnsubscribeRequestParams - - -class ResourceUpdatedNotificationParams(NotificationParams): - \"\"\"Parameters for resource update notifications.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] - \"\"\" - The URI of the resource that has been updated. This might be a sub-resource of the - one that the client actually subscribed to. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ResourceUpdatedNotification( - Notification[ResourceUpdatedNotificationParams, Literal[\"notifications/resources/updated\"]] -): - \"\"\" - A notification from the server to the client, informing it that a resource has - changed and may need to be read again. - \"\"\" - - method: Literal[\"notifications/resources/updated\"] - params: ResourceUpdatedNotificationParams - - -class ListPromptsRequest(ListRequest[Literal[\"prompts/list\"]]): - \"\"\"Sent from the client to request a list of prompts and prompt templates.\"\"\" - - method: Literal[\"prompts/list\"] - - -class PromptArgument(BaseModel): - \"\"\"An argument for a prompt template.\"\"\" - - name: str - \"\"\"The name of the argument.\"\"\" - description: str | None = None - \"\"\"A human-readable description of the argument.\"\"\" - required: bool | None = None - \"\"\"Whether this argument must be provided.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class Prompt(BaseMetadata): - \"\"\"A prompt or prompt template that the server offers.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[\"prompt\"], host_required=False)] - \"\"\"URI for the prompt. Must use 'prompt' scheme.\"\"\" - description: str | None = None - \"\"\"An optional description of what this prompt provides.\"\"\" - arguments: list[PromptArgument] | None = None - \"\"\"A list of arguments to use for templating the prompt.\"\"\" - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ListPromptsResult(ListResult): - \"\"\"The server's response to a prompts/list request from the client.\"\"\" - - prompts: list[Prompt] - - -class GetPromptRequestParams(RequestParams): - \"\"\"Parameters for getting a prompt.\"\"\" - - name: str - \"\"\"The name of the prompt or prompt template.\"\"\" - arguments: dict[str, str] | None = None - \"\"\"Arguments to use for templating the prompt.\"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class GetPromptRequest(Request[GetPromptRequestParams, Literal[\"prompts/get\"]]): - \"\"\"Used by the client to get a prompt provided by the server.\"\"\" - - method: Literal[\"prompts/get\"] - params: GetPromptRequestParams - - -class TextContent(BaseModel): - \"\"\"Text content for a message.\"\"\" - - type: Literal[\"text\"] - text: str - \"\"\"The text content of the message.\"\"\" - annotations: Annotations | None = None - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ImageContent(BaseModel): - \"\"\"Image content for a message.\"\"\" - - type: Literal[\"image\"] - data: str - \"\"\"The base64-encoded image data.\"\"\" - mimeType: str - \"\"\" - The MIME type of the image. Different providers may support different - image types. - \"\"\" - annotations: Annotations | None = None - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class AudioContent(BaseModel): - \"\"\"Audio content for a message.\"\"\" - - type: Literal[\"audio\"] - data: str - \"\"\"The base64-encoded audio data.\"\"\" - mimeType: str - \"\"\" - The MIME type of the audio. Different providers may support different - audio types. - \"\"\" - annotations: Annotations | None = None - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class SamplingMessage(BaseModel): - \"\"\"Describes a message issued to or received from an LLM API.\"\"\" - - role: Role - content: TextContent | ImageContent | AudioContent - model_config = ConfigDict(extra=\"allow\") - - -class EmbeddedResource(BaseModel): - \"\"\" - The contents of a resource, embedded into a prompt or tool call result. - - It is up to the client how best to render embedded resources for the benefit - of the LLM and/or the user. - \"\"\" - - type: Literal[\"resource\"] - resource: TextResourceContents | BlobResourceContents - annotations: Annotations | None = None - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class ResourceLink(Resource): - \"\"\" - A resource that the server is capable of reading, included in a prompt or tool call result. - - Note: resource links returned by tools are not guaranteed to appear in the results of `resources/list` requests. - \"\"\" - - type: Literal[\"resource_link\"] - - -ContentBlock = TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource -\"\"\"A content block that can be used in prompts and tool results.\"\"\" - -Content: TypeAlias = ContentBlock -# \"\"\"DEPRECATED: Content is deprecated, you should use ContentBlock directly.\"\"\" - - -class PromptMessage(BaseModel): - \"\"\"Describes a message returned as part of a prompt.\"\"\" - - role: Role - content: ContentBlock - model_config = ConfigDict(extra=\"allow\") - - -class GetPromptResult(Result): - \"\"\"The server's response to a prompts/get request from the client.\"\"\" - - description: str | None = None - \"\"\"An optional description for the prompt.\"\"\" - messages: list[PromptMessage] - - -class PromptListChangedNotification( - Notification[NotificationParams | None, Literal[\"notifications/prompts/list_changed\"]] -): - \"\"\" - An optional notification from the server to the client, informing it that the list - of prompts it offers has changed. - \"\"\" - - method: Literal[\"notifications/prompts/list_changed\"] - params: NotificationParams | None = None - - -class ListToolsRequest(ListRequest[Literal[\"tools/list\"]]): - \"\"\"Sent from the client to request a list of tools the server has.\"\"\" - - method: Literal[\"tools/list\"] - - -class ToolAnnotations(BaseModel): - \"\"\" - Additional properties describing a Tool to clients. - - NOTE: all properties in ToolAnnotations are **hints**. - They are not guaranteed to provide a faithful description of - tool behavior (including descriptive properties like `title`). - - Clients should never make tool use decisions based on ToolAnnotations - received from untrusted servers. - \"\"\" - - title: str | None = None - \"\"\"A human-readable title for the tool.\"\"\" - - readOnlyHint: bool | None = None - \"\"\" - If true, the tool does not modify its environment. - Default: false - \"\"\" - - destructiveHint: bool | None = None - \"\"\" - If true, the tool may perform destructive updates to its environment. - If false, the tool performs only additive updates. - (This property is meaningful only when `readOnlyHint == false`) - Default: true - \"\"\" - - idempotentHint: bool | None = None - \"\"\" - If true, calling the tool repeatedly with the same arguments - will have no additional effect on the its environment. - (This property is meaningful only when `readOnlyHint == false`) - Default: false - \"\"\" - - openWorldHint: bool | None = None - \"\"\" - If true, this tool may interact with an \"open world\" of external - entities. If false, the tool's domain of interaction is closed. - For example, the world of a web search tool is open, whereas that - of a memory tool is not. - Default: true - \"\"\" - model_config = ConfigDict(extra=\"allow\") - - -class Tool(BaseMetadata): - \"\"\"Definition for a tool the client can call.\"\"\" - - uri: Annotated[AnyUrl, UrlConstraints(allowed_schemes=[\"tool\"], host_required=False)] - \"\"\"URI for the tool. Must use 'tool' scheme.\"\"\" - description: str | None = None - \"\"\"A human-readable description of the tool.\"\"\" - inputSchema: dict[str, Any] - \"\"\"A JSON Schema object defining the expected parameters for the tool.\"\"\" - outputSchema: dict[str, Any] | None = None - \"\"\" - An optional JSON Schema object defining the structure of the tool's output - returned in the structuredContent field of a CallToolResult. - \"\"\" - annotations: ToolAnnotations | None = None - \"\"\"Optional additional tool information.\"\"\" - meta: dict[str, Any] | None = Field(alias=\"_meta\", default=None) - \"\"\" - See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields) - for notes on _meta usage. - \"\"\" - model_config = ConfigDict(extra=\"allow\")" 0 66 (fontified t) 66 70 (face font-lock-keyword-face fontified t) 70 89 (fontified t) 89 95 (face font-lock-keyword-face fontified t) 95 119 (fontified t) 119 123 (face font-lock-keyword-face fontified t) 123 142 (fontified t) 142 148 (face font-lock-keyword-face fontified t) 148 161 (fontified t) 161 163 (face font-lock-string-face fontified t) 163 164 (face font-lock-string-face fontified t syntax-table (15)) 164 949 (face font-lock-string-face fontified t) 949 950 (face font-lock-string-face fontified t syntax-table (15)) 950 952 (face font-lock-string-face fontified t) 952 954 (fontified t) 954 977 (face font-lock-variable-name-face fontified t) 977 978 (fontified t) 978 979 (face font-lock-operator-face fontified t) 979 980 (fontified t) 980 992 (face font-lock-string-face fontified t) 992 994 (fontified t) 994 996 (face font-lock-doc-face fontified t) 996 997 (face font-lock-doc-face fontified t syntax-table (15)) 997 1313 (face font-lock-doc-face fontified t) 1313 1314 (face font-lock-doc-face fontified t syntax-table (15)) 1314 1316 (face font-lock-doc-face fontified t) 1316 1317 (fontified t) 1317 1343 (face font-lock-variable-name-face fontified t) 1343 1344 (fontified t) 1344 1345 (face font-lock-operator-face fontified t) 1345 1346 (fontified t) 1346 1358 (face font-lock-string-face fontified t) 1358 1360 (fontified t) 1360 1369 (face font-lock-variable-name-face fontified t) 1369 1373 (face font-lock-variable-name-face fontified t) 1373 1374 (fontified t) 1374 1375 (face font-lock-operator-face fontified t) 1375 1376 (fontified t) 1376 1379 (face font-lock-builtin-face fontified t) 1379 1380 (fontified t) 1380 1381 (face font-lock-operator-face fontified t) 1381 1382 (fontified t) 1382 1385 (face font-lock-builtin-face fontified t) 1385 1386 (fontified t) 1386 1392 (face font-lock-variable-name-face fontified t) 1392 1393 (fontified t) 1393 1394 (face font-lock-operator-face fontified t) 1394 1395 (fontified t) 1395 1398 (face font-lock-builtin-face fontified t) 1398 1399 (fontified t) 1399 1403 (face font-lock-variable-name-face fontified t) 1403 1404 (fontified t) 1404 1405 (face font-lock-operator-face fontified t) 1405 1413 (fontified t) 1413 1414 (face (rainbow-delimiters-depth-1-face) fontified t) 1414 1420 (face font-lock-string-face fontified t) 1420 1422 (fontified t) 1422 1433 (face font-lock-string-face fontified t) 1433 1434 (face (rainbow-delimiters-depth-1-face) fontified t) 1434 1435 (fontified t) 1435 1444 (face font-lock-variable-name-face fontified t) 1444 1445 (fontified t) 1445 1446 (face font-lock-operator-face fontified t) 1446 1456 (fontified t) 1456 1457 (face (rainbow-delimiters-depth-1-face) fontified t) 1457 1460 (face font-lock-builtin-face fontified t) 1460 1467 (fontified t) 1467 1468 (face (rainbow-delimiters-depth-2-face) fontified t) 1468 1474 (fontified t) 1474 1475 (face font-lock-operator-face fontified t) 1475 1479 (face font-lock-constant-face fontified t) 1479 1480 (face (rainbow-delimiters-depth-2-face) fontified t) 1480 1481 (face (rainbow-delimiters-depth-1-face) fontified t) 1481 1482 (fontified t) 1482 1483 (face font-lock-operator-face fontified t) 1483 1484 (fontified t) 1484 1487 (face font-lock-builtin-face fontified t) 1487 1488 (fontified t) 1488 1499 (face font-lock-variable-name-face fontified t) 1499 1500 (prettify-symbols-end 1632 prettify-symbols-start 1631 composition ((1 32 65 57708)) fontified t) 1500 1511 (fontified t) 1511 1512 (face font-lock-operator-face fontified t) 1512 1521 (fontified t) 1521 1522 (face (rainbow-delimiters-depth-1-face) fontified t) 1522 1530 (fontified t) 1530 1531 (face (rainbow-delimiters-depth-1-face) fontified t) 1531 1534 (fontified t) 1534 1539 (face font-lock-keyword-face fontified t) 1539 1540 (fontified t) 1540 1553 (face font-lock-type-face fontified t) 1553 1554 (face (rainbow-delimiters-depth-1-face) fontified t) 1554 1563 (fontified t) 1563 1564 (face (rainbow-delimiters-depth-1-face) fontified t) 1564 1565 (prettify-symbols-end 1697 prettify-symbols-start 1696 composition (0 1 [32 65 57708]) fontified t) 1565 1570 (fontified t) 1570 1575 (face font-lock-keyword-face fontified t) 1575 1576 (fontified t) 1576 1580 (face font-lock-type-face fontified t) 1580 1581 (face (rainbow-delimiters-depth-1-face) fontified t) 1581 1590 (fontified t) 1590 1591 (face (rainbow-delimiters-depth-1-face) fontified t) 1591 1592 (prettify-symbols-end 1724 prettify-symbols-start 1723 composition (0 1 [32 65 57708]) fontified t) 1592 1614 (fontified t) 1614 1615 (prettify-symbols-end 1747 prettify-symbols-start 1746 composition (0 1 [32 65 57708]) fontified t) 1615 1630 (fontified t) 1630 1631 (face font-lock-operator-face fontified t) 1631 1632 (fontified t) 1632 1636 (face font-lock-constant-face fontified t) 1636 1637 (fontified t) 1637 1638 (face font-lock-operator-face fontified t) 1638 1639 (fontified t) 1639 1643 (face font-lock-constant-face fontified t) 1643 1652 (fontified t) 1652 1654 (face font-lock-doc-face fontified t) 1654 1655 (face font-lock-doc-face fontified t syntax-table (15)) 1655 1990 (face font-lock-doc-face fontified t) 1990 1991 (face font-lock-doc-face fontified t syntax-table (15)) 1991 1993 (face font-lock-doc-face fontified t) 1993 2003 (fontified t) 2003 2015 (face font-lock-variable-name-face fontified t) 2015 2016 (fontified t) 2016 2017 (face font-lock-operator-face fontified t) 2017 2028 (fontified t) 2028 2029 (face (rainbow-delimiters-depth-1-face) fontified t) 2029 2034 (fontified t) 2034 2035 (face font-lock-operator-face fontified t) 2035 2042 (face font-lock-string-face fontified t) 2042 2043 (face (rainbow-delimiters-depth-1-face) fontified t) 2043 2053 (fontified t) 2053 2054 (prettify-symbols-end 2186 prettify-symbols-start 2185 composition (0 1 [32 65 57708]) fontified t) 2054 2060 (fontified t) 2060 2061 (face font-lock-operator-face fontified t) 2061 2062 (fontified t) 2062 2066 (face font-lock-constant-face fontified t) 2066 2067 (fontified t) 2067 2068 (face font-lock-operator-face fontified t) 2068 2074 (fontified t) 2074 2075 (face (rainbow-delimiters-depth-1-face) fontified t) 2075 2080 (fontified t) 2080 2081 (face font-lock-operator-face fontified t) 2081 2088 (face font-lock-string-face fontified t) 2088 2097 (fontified t) 2097 2098 (face font-lock-operator-face fontified t) 2098 2102 (face font-lock-constant-face fontified t) 2102 2103 (face (rainbow-delimiters-depth-1-face) fontified t) 2103 2106 (fontified t) 2106 2111 (face font-lock-keyword-face fontified t) 2111 2112 (fontified t) 2112 2129 (face font-lock-type-face fontified t) 2129 2130 (face (rainbow-delimiters-depth-1-face) fontified t) 2130 2143 (fontified t) 2143 2144 (face (rainbow-delimiters-depth-1-face) fontified t) 2144 2145 (prettify-symbols-end 2277 prettify-symbols-start 2276 composition (0 1 [32 65 57708]) fontified t) 2145 2156 (fontified t) 2156 2157 (prettify-symbols-end 2289 prettify-symbols-start 2288 composition (0 1 [32 65 57708]) fontified t) 2157 2158 (fontified t) 2158 2161 (face font-lock-builtin-face fontified t) 2161 2162 (fontified t) 2162 2163 (face font-lock-operator-face fontified t) 2163 2164 (fontified t) 2164 2168 (face font-lock-constant-face fontified t) 2168 2169 (fontified t) 2169 2170 (face font-lock-operator-face fontified t) 2170 2171 (fontified t) 2171 2175 (face font-lock-constant-face fontified t) 2175 2180 (fontified t) 2180 2182 (face font-lock-doc-face fontified t) 2182 2183 (face font-lock-doc-face fontified t syntax-table (15)) 2183 2224 (face font-lock-doc-face fontified t) 2224 2225 (face font-lock-doc-face fontified t syntax-table (15)) 2225 2227 (face font-lock-doc-face fontified t) 2227 2239 (fontified t) 2239 2240 (prettify-symbols-end 2372 prettify-symbols-start 2371 composition (0 1 [32 65 57708]) fontified t) 2240 2248 (fontified t) 2248 2249 (face font-lock-operator-face fontified t) 2249 2250 (fontified t) 2250 2254 (face font-lock-constant-face fontified t) 2254 2255 (fontified t) 2255 2256 (face font-lock-operator-face fontified t) 2256 2257 (fontified t) 2257 2261 (face font-lock-constant-face fontified t) 2261 2266 (fontified t) 2266 2268 (face font-lock-doc-face fontified t) 2268 2269 (face font-lock-doc-face fontified t syntax-table (15)) 2269 2418 (face font-lock-doc-face fontified t) 2418 2419 (face font-lock-doc-face fontified t syntax-table (15)) 2419 2421 (face font-lock-doc-face fontified t) 2421 2424 (fontified t) 2424 2429 (face font-lock-keyword-face fontified t) 2429 2430 (fontified t) 2430 2448 (face font-lock-type-face fontified t) 2448 2449 (face (rainbow-delimiters-depth-1-face) fontified t) 2449 2458 (fontified t) 2458 2459 (face (rainbow-delimiters-depth-1-face) fontified t) 2459 2460 (prettify-symbols-end 2592 prettify-symbols-start 2591 composition (0 1 [32 65 57708]) fontified t) 2460 2465 (fontified t) 2465 2470 (face font-lock-keyword-face fontified t) 2470 2471 (fontified t) 2471 2475 (face font-lock-type-face fontified t) 2475 2476 (face (rainbow-delimiters-depth-1-face) fontified t) 2476 2485 (fontified t) 2485 2486 (face (rainbow-delimiters-depth-1-face) fontified t) 2486 2487 (prettify-symbols-end 2619 prettify-symbols-start 2618 composition (0 1 [32 65 57708]) fontified t) 2487 2496 (fontified t) 2496 2508 (face font-lock-variable-name-face fontified t) 2508 2509 (fontified t) 2509 2510 (face font-lock-operator-face fontified t) 2510 2521 (fontified t) 2521 2522 (face (rainbow-delimiters-depth-1-face) fontified t) 2522 2527 (fontified t) 2527 2528 (face font-lock-operator-face fontified t) 2528 2535 (face font-lock-string-face fontified t) 2535 2536 (face (rainbow-delimiters-depth-1-face) fontified t) 2536 2546 (fontified t) 2546 2547 (prettify-symbols-end 2679 prettify-symbols-start 2678 composition (0 1 [32 65 57708]) fontified t) 2547 2553 (fontified t) 2553 2554 (face font-lock-operator-face fontified t) 2554 2555 (fontified t) 2555 2559 (face font-lock-constant-face fontified t) 2559 2560 (fontified t) 2560 2561 (face font-lock-operator-face fontified t) 2561 2567 (fontified t) 2567 2568 (face (rainbow-delimiters-depth-1-face) fontified t) 2568 2573 (fontified t) 2573 2574 (face font-lock-operator-face fontified t) 2574 2581 (face font-lock-string-face fontified t) 2581 2590 (fontified t) 2590 2591 (face font-lock-operator-face fontified t) 2591 2595 (face font-lock-constant-face fontified t) 2595 2596 (face (rainbow-delimiters-depth-1-face) fontified t) 2596 2601 (fontified t) 2601 2603 (face font-lock-doc-face fontified t) 2603 2604 (face font-lock-doc-face fontified t syntax-table (15)) 2604 2831 (face font-lock-doc-face fontified t) 2831 2832 (face font-lock-doc-face fontified t syntax-table (15)) 2832 2834 (face font-lock-doc-face fontified t) 2834 2837 (fontified t) 2837 2851 (face font-lock-variable-name-face fontified t) 2851 2852 (fontified t) 2852 2853 (face font-lock-operator-face fontified t) 2853 2861 (fontified t) 2861 2862 (face (rainbow-delimiters-depth-1-face) fontified t) 2862 2878 (face font-lock-string-face fontified t) 2878 2885 (fontified t) 2885 2886 (face font-lock-operator-face fontified t) 2886 2900 (fontified t) 2900 2901 (face font-lock-operator-face fontified t) 2901 2902 (fontified t) 2902 2906 (face font-lock-builtin-face fontified t) 2906 2907 (face (rainbow-delimiters-depth-2-face) fontified t) 2907 2910 (face font-lock-builtin-face fontified t) 2910 2915 (fontified t) 2915 2916 (face (rainbow-delimiters-depth-2-face) fontified t) 2916 2917 (fontified t) 2917 2918 (face font-lock-operator-face fontified t) 2918 2919 (fontified t) 2919 2923 (face font-lock-constant-face fontified t) 2923 2924 (face (rainbow-delimiters-depth-1-face) fontified t) 2924 2925 (fontified t) 2925 2944 (face font-lock-variable-name-face fontified t) 2944 2945 (fontified t) 2945 2946 (face font-lock-operator-face fontified t) 2946 2954 (fontified t) 2954 2955 (face (rainbow-delimiters-depth-1-face) fontified t) 2955 2976 (face font-lock-string-face fontified t) 2976 2983 (fontified t) 2983 2984 (face font-lock-operator-face fontified t) 2984 3003 (fontified t) 3003 3004 (face font-lock-operator-face fontified t) 3004 3005 (fontified t) 3005 3009 (face font-lock-builtin-face fontified t) 3009 3010 (face (rainbow-delimiters-depth-2-face) fontified t) 3010 3013 (face font-lock-builtin-face fontified t) 3013 3018 (fontified t) 3018 3019 (face (rainbow-delimiters-depth-2-face) fontified t) 3019 3020 (fontified t) 3020 3021 (face font-lock-operator-face fontified t) 3021 3022 (fontified t) 3022 3026 (face font-lock-constant-face fontified t) 3026 3027 (face (rainbow-delimiters-depth-1-face) fontified t) 3027 3028 (fontified t) 3028 3034 (face font-lock-variable-name-face fontified t) 3034 3035 (fontified t face font-lock-variable-name-face) 3035 3036 (fontified t) 3036 3037 (fontified t face font-lock-operator-face) 3037 3045 (fontified t) 3045 3046 (fontified t face (rainbow-delimiters-depth-1-face)) 3046 3055 (fontified t face font-lock-string-face) 3055 3062 (fontified t) 3062 3063 (fontified t face font-lock-operator-face) 3063 3066 (fontified t face font-lock-builtin-face) 3066 3067 (fontified t face (rainbow-delimiters-depth-1-face)) 3067 3068 (fontified t) 3068 3070 (fontified t) 3070 3075 (face font-lock-keyword-face fontified t) 3075 3076 (fontified t) 3076 3083 (face font-lock-type-face fontified t) 3083 3084 (face (rainbow-delimiters-depth-1-face) fontified t) 3084 3102 (fontified t) 3102 3103 (face (rainbow-delimiters-depth-2-face) fontified t) 3103 3126 (fontified t) 3126 3127 (face (rainbow-delimiters-depth-2-face) fontified t) 3127 3128 (face (rainbow-delimiters-depth-1-face) fontified t) 3128 3129 (prettify-symbols-end 3261 prettify-symbols-start 3260 composition (0 1 [32 65 57708]) fontified t) 3129 3134 (fontified t) 3134 3136 (face font-lock-doc-face fontified t) 3136 3137 (face font-lock-doc-face fontified t syntax-table (15)) 3137 3170 (face font-lock-doc-face fontified t) 3170 3171 (face font-lock-doc-face fontified t syntax-table (15)) 3171 3173 (face font-lock-doc-face fontified t) 3173 3185 (fontified t) 3185 3186 (prettify-symbols-end 3318 prettify-symbols-start 3317 composition (0 1 [32 65 57708]) fontified t) 3186 3205 (fontified t) 3205 3206 (prettify-symbols-end 3338 prettify-symbols-start 3337 composition (0 1 [32 65 57708]) fontified t) 3206 3226 (fontified t) 3226 3238 (face font-lock-variable-name-face fontified t) 3238 3239 (fontified t) 3239 3240 (face font-lock-operator-face fontified t) 3240 3251 (fontified t) 3251 3252 (face (rainbow-delimiters-depth-1-face) fontified t) 3252 3257 (fontified t) 3257 3258 (face font-lock-operator-face fontified t) 3258 3265 (face font-lock-string-face fontified t) 3265 3266 (face (rainbow-delimiters-depth-1-face) fontified t) 3266 3269 (fontified t) 3269 3274 (face font-lock-keyword-face fontified t) 3274 3275 (fontified t) 3275 3286 (face font-lock-type-face fontified t) 3286 3287 (face (rainbow-delimiters-depth-1-face) fontified t) 3287 3294 (fontified t) 3294 3295 (face (rainbow-delimiters-depth-2-face) fontified t) 3295 3313 (fontified t) 3313 3314 (face font-lock-operator-face fontified t) 3314 3315 (fontified t) 3315 3319 (face font-lock-constant-face fontified t) 3319 3328 (fontified t) 3328 3329 (face (rainbow-delimiters-depth-2-face) fontified t) 3329 3338 (fontified t) 3338 3339 (face (rainbow-delimiters-depth-2-face) fontified t) 3339 3346 (fontified t) 3346 3347 (face (rainbow-delimiters-depth-2-face) fontified t) 3347 3348 (face (rainbow-delimiters-depth-1-face) fontified t) 3348 3349 (prettify-symbols-end 3481 prettify-symbols-start 3480 composition (0 1 [32 65 57708]) fontified t) 3349 3354 (fontified t) 3354 3356 (face font-lock-doc-face fontified t) 3356 3357 (face font-lock-doc-face fontified t syntax-table (15)) 3357 3435 (face font-lock-doc-face fontified t) 3435 3436 (face font-lock-doc-face fontified t syntax-table (15)) 3436 3438 (face font-lock-doc-face fontified t) 3438 3450 (fontified t) 3450 3451 (prettify-symbols-end 3583 prettify-symbols-start 3582 composition (0 1 [32 65 57708]) fontified t) 3451 3470 (fontified t) 3470 3471 (face font-lock-operator-face fontified t) 3471 3472 (fontified t) 3472 3476 (face font-lock-constant-face fontified t) 3476 3477 (fontified t) 3477 3478 (face font-lock-operator-face fontified t) 3478 3479 (fontified t) 3479 3483 (face font-lock-constant-face fontified t) 3483 3486 (fontified t) 3486 3491 (face font-lock-keyword-face fontified t) 3491 3492 (fontified t) 3492 3504 (face font-lock-type-face fontified t) 3504 3505 (face (rainbow-delimiters-depth-1-face) fontified t) 3505 3523 (fontified t) 3523 3524 (face (rainbow-delimiters-depth-2-face) fontified t) 3524 3552 (fontified t) 3552 3553 (face (rainbow-delimiters-depth-2-face) fontified t) 3553 3554 (face (rainbow-delimiters-depth-1-face) fontified t) 3554 3555 (prettify-symbols-end 3687 prettify-symbols-start 3686 composition (0 1 [32 65 57708]) fontified t) 3555 3560 (fontified t) 3560 3562 (face font-lock-doc-face fontified t) 3562 3563 (face font-lock-doc-face fontified t syntax-table (15)) 3563 3601 (face font-lock-doc-face fontified t) 3601 3602 (face font-lock-doc-face fontified t syntax-table (15)) 3602 3604 (face font-lock-doc-face fontified t) 3604 3616 (fontified t) 3616 3617 (prettify-symbols-end 3749 prettify-symbols-start 3748 composition (0 1 [32 65 57708]) fontified t) 3617 3636 (fontified t) 3636 3637 (prettify-symbols-end 3769 prettify-symbols-start 3768 composition (0 1 [32 65 57708]) fontified t) 3637 3662 (fontified t) 3662 3674 (face font-lock-variable-name-face fontified t) 3674 3675 (fontified t) 3675 3676 (face font-lock-operator-face fontified t) 3676 3687 (fontified t) 3687 3688 (face (rainbow-delimiters-depth-1-face) fontified t) 3688 3693 (fontified t) 3693 3694 (face font-lock-operator-face fontified t) 3694 3701 (face font-lock-string-face fontified t) 3701 3702 (face (rainbow-delimiters-depth-1-face) fontified t) 3702 3705 (fontified t) 3705 3710 (face font-lock-keyword-face fontified t) 3710 3711 (fontified t) 3711 3717 (face font-lock-type-face fontified t) 3717 3718 (face (rainbow-delimiters-depth-1-face) fontified t) 3718 3727 (fontified t) 3727 3728 (face (rainbow-delimiters-depth-1-face) fontified t) 3728 3729 (prettify-symbols-end 3861 prettify-symbols-start 3860 composition (0 1 [32 65 57708]) fontified t) 3729 3734 (fontified t) 3734 3736 (face font-lock-doc-face fontified t) 3736 3737 (face font-lock-doc-face fontified t syntax-table (15)) 3737 3769 (face font-lock-doc-face fontified t) 3769 3770 (face font-lock-doc-face fontified t syntax-table (15)) 3770 3772 (face font-lock-doc-face fontified t) 3772 3782 (fontified t) 3782 3783 (prettify-symbols-end 3915 prettify-symbols-start 3914 composition (0 1 [32 65 57708]) fontified t) 3783 3784 (fontified t) 3784 3788 (face font-lock-builtin-face fontified t) 3788 3789 (face (rainbow-delimiters-depth-1-face) fontified t) 3789 3792 (face font-lock-builtin-face fontified t) 3792 3797 (fontified t) 3797 3798 (face (rainbow-delimiters-depth-1-face) fontified t) 3798 3799 (fontified t) 3799 3800 (face font-lock-operator-face fontified t) 3800 3801 (fontified t) 3801 3805 (face font-lock-constant-face fontified t) 3805 3806 (fontified t) 3806 3807 (face font-lock-operator-face fontified t) 3807 3813 (fontified t) 3813 3814 (face (rainbow-delimiters-depth-1-face) fontified t) 3814 3819 (fontified t) 3819 3820 (face font-lock-operator-face fontified t) 3820 3827 (face font-lock-string-face fontified t) 3827 3836 (fontified t) 3836 3837 (face font-lock-operator-face fontified t) 3837 3841 (face font-lock-constant-face fontified t) 3841 3842 (face (rainbow-delimiters-depth-1-face) fontified t) 3842 3847 (fontified t) 3847 3849 (face font-lock-doc-face fontified t) 3849 3850 (face font-lock-doc-face fontified t syntax-table (15)) 3850 4077 (face font-lock-doc-face fontified t) 4077 4078 (face font-lock-doc-face fontified t syntax-table (15)) 4078 4080 (face font-lock-doc-face fontified t) 4080 4085 (fontified t) 4085 4097 (face font-lock-variable-name-face fontified t) 4097 4098 (fontified t) 4098 4099 (face font-lock-operator-face fontified t) 4099 4110 (fontified t) 4110 4111 (face (rainbow-delimiters-depth-1-face) fontified t) 4111 4116 (fontified t) 4116 4117 (face font-lock-operator-face fontified t) 4117 4124 (face font-lock-string-face fontified t) 4124 4125 (face (rainbow-delimiters-depth-1-face) fontified t) 4125 4128 (fontified t) 4128 4133 (face font-lock-keyword-face fontified t) 4133 4134 (fontified t) 4134 4144 (face font-lock-type-face fontified t) 4144 4145 (face (rainbow-delimiters-depth-1-face) fontified t) 4145 4151 (fontified t) 4151 4152 (face (rainbow-delimiters-depth-1-face) fontified t) 4152 4153 (prettify-symbols-end 4285 prettify-symbols-start 4284 composition ((1 32 65 57708)) fontified t) 4153 4168 (fontified t) 4168 4169 (prettify-symbols-end 4301 prettify-symbols-start 4300 composition ((1 32 65 57708)) fontified t) 4169 4177 (fontified t) 4177 4178 (face font-lock-operator-face fontified t) 4178 4179 (fontified t) 4179 4183 (face font-lock-constant-face fontified t) 4183 4184 (fontified t) 4184 4185 (face font-lock-operator-face fontified t) 4185 4186 (fontified t) 4186 4190 (face font-lock-constant-face fontified t) 4190 4195 (fontified t) 4195 4197 (face font-lock-doc-face fontified t) 4197 4198 (face font-lock-doc-face fontified t syntax-table (15)) 4198 4345 (face font-lock-doc-face fontified t) 4345 4346 (face font-lock-doc-face fontified t syntax-table (15)) 4346 4348 (face font-lock-doc-face fontified t) 4348 4351 (fontified t) 4351 4356 (face font-lock-keyword-face fontified t) 4356 4357 (fontified t) 4357 4371 (face font-lock-type-face fontified t) 4371 4372 (face (rainbow-delimiters-depth-1-face) fontified t) 4372 4379 (fontified t) 4379 4380 (face (rainbow-delimiters-depth-2-face) fontified t) 4380 4384 (face font-lock-builtin-face fontified t) 4384 4385 (face (rainbow-delimiters-depth-3-face) fontified t) 4385 4388 (face font-lock-builtin-face fontified t) 4388 4393 (fontified t) 4393 4394 (face (rainbow-delimiters-depth-3-face) fontified t) 4394 4395 (fontified t) 4395 4396 (face font-lock-operator-face fontified t) 4396 4397 (fontified t) 4397 4401 (face font-lock-constant-face fontified t) 4401 4403 (fontified t) 4403 4406 (face font-lock-builtin-face fontified t) 4406 4407 (face (rainbow-delimiters-depth-2-face) fontified t) 4407 4408 (face (rainbow-delimiters-depth-1-face) fontified t) 4408 4409 (prettify-symbols-end 4541 prettify-symbols-start 4540 composition (0 1 [32 65 57708]) fontified t) 4409 4414 (fontified t) 4414 4416 (face font-lock-doc-face fontified t) 4416 4417 (face font-lock-doc-face fontified t syntax-table (15)) 4417 4425 (face font-lock-doc-face fontified t) 4425 4451 (face font-lock-doc-face fontified t) 4451 4452 (face font-lock-doc-face fontified t syntax-table (15)) 4452 4454 (face font-lock-doc-face fontified t) 4454 4455 (fontified t) 4455 4467 (fontified t) 4467 4468 (prettify-symbols-end 4600 prettify-symbols-start 4599 composition (0 1 [32 65 57708]) fontified t) 4468 4476 (fontified t) 4476 4477 (face (rainbow-delimiters-depth-1-face) fontified t) 4477 4482 (face font-lock-string-face fontified t) 4482 4483 (face (rainbow-delimiters-depth-1-face) fontified t) 4483 4488 (fontified t) 4488 4490 (face font-lock-builtin-face fontified t) 4490 4491 (prettify-symbols-end 4623 prettify-symbols-start 4622 composition (0 1 [32 65 57708]) fontified t) 4491 4512 (fontified t) 4512 4513 (prettify-symbols-end 4645 prettify-symbols-start 4644 composition (0 1 [32 65 57708]) fontified t) 4513 4514 (fontified t) 4514 4517 (face font-lock-builtin-face fontified t) 4517 4528 (fontified t) 4528 4529 (prettify-symbols-end 4661 prettify-symbols-start 4660 composition (0 1 [32 65 57708]) fontified t) 4529 4530 (fontified t) 4530 4534 (face font-lock-builtin-face fontified t) 4534 4535 (face (rainbow-delimiters-depth-1-face) fontified t) 4535 4538 (face font-lock-builtin-face fontified t) 4538 4543 (fontified t) 4543 4544 (face (rainbow-delimiters-depth-1-face) fontified t) 4544 4545 (fontified t) 4545 4546 (face font-lock-operator-face fontified t) 4546 4547 (fontified t) 4547 4551 (face font-lock-constant-face fontified t) 4551 4552 (fontified t) 4552 4553 (face font-lock-operator-face fontified t) 4553 4554 (fontified t) 4554 4558 (face font-lock-constant-face fontified t) 4558 4561 (fontified t) 4561 4566 (face font-lock-keyword-face fontified t) 4566 4567 (fontified t) 4567 4568 (face font-lock-type-face fontified t) 4568 4586 (fontified t face font-lock-type-face) 4586 4587 (fontified t face (rainbow-delimiters-depth-1-face)) 4587 4599 (fontified t) 4599 4600 (fontified t face (rainbow-delimiters-depth-2-face)) 4600 4604 (fontified t face font-lock-builtin-face) 4604 4605 (fontified t face (rainbow-delimiters-depth-3-face)) 4605 4608 (fontified t face font-lock-builtin-face) 4608 4613 (fontified t) 4613 4614 (fontified t face (rainbow-delimiters-depth-3-face)) 4614 4615 (fontified t) 4615 4616 (fontified t face font-lock-operator-face) 4616 4617 (fontified t) 4617 4621 (fontified t face font-lock-constant-face) 4621 4623 (fontified t) 4623 4626 (fontified t face font-lock-builtin-face) 4626 4627 (fontified t face (rainbow-delimiters-depth-2-face)) 4627 4628 (fontified t face (rainbow-delimiters-depth-1-face)) 4628 4629 (fontified t prettify-symbols-end 4761 prettify-symbols-start 4760 composition (0 1 [32 65 57708])) 4629 4630 (fontified t) 4630 4634 (fontified t) 4634 4636 (face font-lock-doc-face fontified t) 4636 4637 (face font-lock-doc-face fontified t syntax-table (15)) 4637 4685 (face font-lock-doc-face fontified t) 4685 4686 (face font-lock-doc-face fontified t syntax-table (15)) 4686 4688 (face font-lock-doc-face fontified t) 4688 4701 (fontified t) 4701 4702 (prettify-symbols-end 4834 prettify-symbols-start 4833 composition (0 1 [32 65 57708]) fontified t) 4702 4710 (fontified t) 4710 4711 (face (rainbow-delimiters-depth-1-face) fontified t) 4711 4716 (face font-lock-string-face fontified t) 4716 4717 (face (rainbow-delimiters-depth-1-face) fontified t) 4717 4728 (fontified t) 4728 4729 (prettify-symbols-end 4861 prettify-symbols-start 4860 composition (0 1 [32 65 57708]) fontified t) 4729 4730 (fontified t) 4730 4734 (face font-lock-builtin-face fontified t) 4734 4735 (face (rainbow-delimiters-depth-1-face) fontified t) 4735 4738 (face font-lock-builtin-face fontified t) 4738 4743 (fontified t) 4743 4744 (face (rainbow-delimiters-depth-1-face) fontified t) 4744 4745 (fontified t) 4745 4746 (face font-lock-operator-face fontified t) 4746 4747 (fontified t) 4747 4751 (face font-lock-constant-face fontified t) 4751 4752 (fontified t) 4752 4753 (face font-lock-operator-face fontified t) 4753 4754 (fontified t) 4754 4758 (face font-lock-constant-face fontified t) 4758 4761 (fontified t) 4761 4766 (face font-lock-keyword-face fontified t) 4766 4767 (fontified t) 4767 4782 (face font-lock-type-face fontified t) 4782 4783 (face (rainbow-delimiters-depth-1-face) fontified t) 4783 4792 (fontified t) 4792 4793 (face (rainbow-delimiters-depth-1-face) fontified t) 4793 4794 (prettify-symbols-end 4926 prettify-symbols-start 4925 composition (0 1 [32 65 57708]) fontified t) 4794 4799 (fontified t) 4799 4801 (face font-lock-doc-face fontified t) 4801 4802 (face font-lock-doc-face fontified t syntax-table (15)) 4802 4849 (face font-lock-doc-face fontified t) 4849 4850 (face font-lock-doc-face fontified t syntax-table (15)) 4850 4852 (face font-lock-doc-face fontified t) 4852 4865 (fontified t) 4865 4866 (prettify-symbols-end 4998 prettify-symbols-start 4997 composition (0 1 [32 65 57708]) fontified t) 4866 4874 (fontified t) 4874 4875 (face (rainbow-delimiters-depth-1-face) fontified t) 4875 4880 (face font-lock-string-face fontified t) 4880 4881 (face (rainbow-delimiters-depth-1-face) fontified t) 4881 4886 (fontified t) 4886 4888 (face font-lock-builtin-face fontified t) 4888 4889 (prettify-symbols-end 5021 prettify-symbols-start 5020 composition (0 1 [32 65 57708]) fontified t) 4889 4910 (fontified t) 4910 4911 (prettify-symbols-end 5043 prettify-symbols-start 5042 composition (0 1 [32 65 57708]) fontified t) 4911 4912 (fontified t) 4912 4916 (face font-lock-builtin-face fontified t) 4916 4917 (face (rainbow-delimiters-depth-1-face) fontified t) 4917 4920 (face font-lock-builtin-face fontified t) 4920 4925 (fontified t) 4925 4926 (face (rainbow-delimiters-depth-1-face) fontified t) 4926 4931 (fontified t) 4931 4943 (face font-lock-variable-name-face fontified t) 4943 4944 (fontified t) 4944 4945 (face font-lock-operator-face fontified t) 4945 4956 (fontified t) 4956 4957 (face (rainbow-delimiters-depth-1-face) fontified t) 4957 4962 (fontified t) 4962 4963 (face font-lock-operator-face fontified t) 4963 4970 (face font-lock-string-face fontified t) 4970 4971 (face (rainbow-delimiters-depth-1-face) fontified t) 4971 4974 (fontified t) 4974 4976 (face font-lock-comment-delimiter-face fontified t) 4976 4992 (face font-lock-comment-face fontified t) 4992 5009 (face font-lock-variable-name-face fontified t) 5009 5010 (fontified t) 5010 5011 (face font-lock-operator-face fontified t) 5011 5012 (fontified t) 5012 5013 (face font-lock-operator-face fontified t) 5013 5019 (fontified t) 5019 5021 (face font-lock-comment-delimiter-face fontified t) 5021 5078 (face font-lock-comment-face fontified t) 5078 5079 (fontified t) 5079 5081 (face font-lock-comment-delimiter-face fontified t) 5081 5111 (face font-lock-comment-face fontified t) 5111 5122 (face font-lock-variable-name-face fontified t) 5122 5123 (fontified t) 5123 5124 (face font-lock-operator-face fontified t) 5124 5125 (fontified t) 5125 5126 (face font-lock-operator-face fontified t) 5126 5132 (fontified t) 5132 5147 (face font-lock-variable-name-face fontified t) 5147 5148 (fontified t) 5148 5149 (face font-lock-operator-face fontified t) 5149 5150 (fontified t) 5150 5151 (face font-lock-operator-face fontified t) 5151 5157 (fontified t) 5157 5173 (face font-lock-variable-name-face fontified t) 5173 5174 (fontified t) 5174 5175 (face font-lock-operator-face fontified t) 5175 5176 (fontified t) 5176 5177 (face font-lock-operator-face fontified t) 5177 5183 (fontified t) 5183 5197 (face font-lock-variable-name-face fontified t) 5197 5198 (fontified t) 5198 5199 (face font-lock-operator-face fontified t) 5199 5200 (fontified t) 5200 5201 (face font-lock-operator-face fontified t) 5201 5207 (fontified t) 5207 5221 (face font-lock-variable-name-face fontified t) 5221 5222 (fontified t) 5222 5223 (face font-lock-operator-face fontified t) 5223 5224 (fontified t) 5224 5225 (face font-lock-operator-face fontified t) 5225 5233 (fontified t) 5233 5238 (face font-lock-keyword-face fontified t) 5238 5239 (fontified t) 5239 5248 (face font-lock-type-face fontified t) 5248 5249 (face (rainbow-delimiters-depth-1-face) fontified t) 5249 5258 (fontified t) 5258 5259 (face (rainbow-delimiters-depth-1-face) fontified t) 5259 5260 (prettify-symbols-end 5392 prettify-symbols-start 5391 composition (0 1 [32 65 57708]) fontified t) 5260 5265 (fontified t) 5265 5267 (face font-lock-doc-face fontified t) 5267 5268 (face font-lock-doc-face syntax-table (15) fontified t) 5268 5315 (face font-lock-doc-face fontified t) 5315 5316 (face font-lock-doc-face syntax-table (15) fontified t) 5316 5318 (face font-lock-doc-face fontified t) 5318 5328 (fontified t) 5328 5329 (prettify-symbols-end 5461 prettify-symbols-start 5460 composition (0 1 [32 65 57708]) fontified t) 5329 5330 (fontified t) 5330 5333 (face font-lock-builtin-face fontified t) 5333 5338 (fontified t) 5338 5340 (face font-lock-string-face fontified t) 5340 5341 (face font-lock-string-face syntax-table (15) fontified t) 5341 5370 (face font-lock-string-face fontified t) 5370 5371 (face font-lock-string-face syntax-table (15) fontified t) 5371 5373 (face font-lock-string-face fontified t) 5373 5386 (fontified t) 5386 5387 (prettify-symbols-end 5519 prettify-symbols-start 5518 composition (0 1 [32 65 57708]) fontified t) 5387 5388 (fontified t) 5388 5391 (face font-lock-builtin-face fontified t) 5391 5396 (fontified t) 5396 5398 (face font-lock-string-face fontified t) 5398 5399 (face font-lock-string-face syntax-table (15) fontified t) 5399 5506 (face font-lock-string-face fontified t) 5506 5507 (face font-lock-string-face syntax-table (15) fontified t) 5507 5509 (face font-lock-string-face fontified t) 5509 5519 (fontified t) 5519 5520 (prettify-symbols-end 5652 prettify-symbols-start 5651 composition (0 1 [32 65 57708]) fontified t) 5520 5525 (fontified t) 5525 5526 (face font-lock-operator-face fontified t) 5526 5527 (fontified t) 5527 5531 (face font-lock-constant-face fontified t) 5531 5532 (fontified t) 5532 5533 (face font-lock-operator-face fontified t) 5533 5534 (fontified t) 5534 5538 (face font-lock-constant-face fontified t) 5538 5543 (fontified t) 5543 5545 (face font-lock-doc-face fontified t) 5545 5546 (face font-lock-doc-face syntax-table (15) fontified t) 5546 5704 (face font-lock-doc-face fontified t) 5704 5705 (face font-lock-doc-face syntax-table (15) fontified t) 5705 5707 (face font-lock-doc-face fontified t) 5707 5713 (fontified t) 5713 5725 (face font-lock-variable-name-face fontified t) 5725 5726 (fontified t) 5726 5727 (face font-lock-operator-face fontified t) 5727 5738 (fontified t) 5738 5739 (face (rainbow-delimiters-depth-1-face) fontified t) 5739 5744 (fontified t) 5744 5745 (face font-lock-operator-face fontified t) 5745 5752 (face font-lock-string-face fontified t) 5752 5753 (face (rainbow-delimiters-depth-1-face) fontified t) 5753 5756 (fontified t) 5756 5761 (face font-lock-keyword-face fontified t) 5761 5762 (fontified t) 5762 5774 (face font-lock-type-face fontified t) 5774 5775 (face (rainbow-delimiters-depth-1-face) fontified t) 5775 5784 (fontified t) 5784 5785 (face (rainbow-delimiters-depth-1-face) fontified t) 5785 5786 (prettify-symbols-end 5918 prettify-symbols-start 5917 composition (0 1 [32 65 57708]) fontified t) 5786 5791 (fontified t) 5791 5793 (face font-lock-doc-face fontified t) 5793 5794 (face font-lock-doc-face syntax-table (15) fontified t) 5794 5851 (face font-lock-doc-face fontified t) 5851 5852 (face font-lock-doc-face syntax-table (15) fontified t) 5852 5854 (face font-lock-doc-face fontified t) 5854 5867 (fontified t) 5867 5868 (prettify-symbols-end 6000 prettify-symbols-start 5999 composition ((1 32 65 57708)) fontified t) 5868 5876 (fontified t) 5876 5877 (face (rainbow-delimiters-depth-1-face) fontified t) 5877 5882 (face font-lock-string-face fontified t) 5882 5883 (face (rainbow-delimiters-depth-1-face) fontified t) 5883 5888 (fontified t) 5888 5890 (face font-lock-builtin-face fontified t) 5890 5891 (prettify-symbols-end 6023 prettify-symbols-start 6022 composition ((1 32 65 57708)) fontified t) 5891 5892 (fontified t) 5892 5895 (face font-lock-builtin-face fontified t) 5895 5896 (fontified t) 5896 5897 (face font-lock-operator-face fontified t) 5897 5898 (fontified t) 5898 5901 (face font-lock-builtin-face fontified t) 5901 5911 (fontified t) 5911 5912 (prettify-symbols-end 6044 prettify-symbols-start 6043 composition ((1 32 65 57708)) fontified t) 5912 5927 (fontified t) 5927 5939 (face font-lock-variable-name-face fontified t) 5939 5940 (fontified t) 5940 5941 (face font-lock-operator-face fontified t) 5941 5952 (fontified t) 5952 5953 (face (rainbow-delimiters-depth-1-face) fontified t) 5953 5958 (fontified t) 5958 5959 (face font-lock-operator-face fontified t) 5959 5966 (face font-lock-string-face fontified t) 5966 5967 (face (rainbow-delimiters-depth-1-face) fontified t) 5967 5970 (fontified t) 5970 5975 (face font-lock-keyword-face fontified t) 5975 5976 (fontified t) 5976 5990 (face font-lock-type-face fontified t) 5990 5991 (face (rainbow-delimiters-depth-1-face) fontified t) 5991 6000 (fontified t) 6000 6001 (face (rainbow-delimiters-depth-2-face) fontified t) 6001 6016 (fontified t) 6016 6017 (face font-lock-operator-face fontified t) 6017 6038 (fontified t) 6038 6039 (face font-lock-operator-face fontified t) 6039 6056 (fontified t) 6056 6057 (face font-lock-operator-face fontified t) 6057 6070 (fontified t) 6070 6071 (face (rainbow-delimiters-depth-2-face) fontified t) 6071 6072 (face (rainbow-delimiters-depth-1-face) fontified t) 6072 6073 (prettify-symbols-end 6205 prettify-symbols-start 6204 composition (0 1 [32 65 57708]) fontified t) 6073 6078 (fontified t) 6078 6082 (face font-lock-keyword-face fontified t) 6082 6085 (fontified t) 6085 6090 (face font-lock-keyword-face fontified t) 6090 6091 (fontified t) 6091 6102 (face font-lock-type-face fontified t) 6102 6103 (face (rainbow-delimiters-depth-1-face) fontified t) 6103 6109 (fontified t) 6109 6110 (face (rainbow-delimiters-depth-1-face) fontified t) 6110 6111 (prettify-symbols-end 6243 prettify-symbols-start 6242 composition (0 1 [32 65 57708]) fontified t) 6111 6116 (fontified t) 6116 6118 (face font-lock-doc-face fontified t) 6118 6119 (face font-lock-doc-face syntax-table (15) fontified t) 6119 6173 (face font-lock-doc-face fontified t) 6173 6174 (face font-lock-doc-face syntax-table (15) fontified t) 6174 6176 (face font-lock-doc-face fontified t) 6176 6179 (fontified t) 6179 6184 (face font-lock-keyword-face fontified t) 6184 6185 (fontified t) 6185 6197 (face font-lock-type-face fontified t) 6197 6198 (face (rainbow-delimiters-depth-1-face) fontified t) 6198 6207 (fontified t) 6207 6208 (face (rainbow-delimiters-depth-1-face) fontified t) 6208 6209 (prettify-symbols-end 6341 prettify-symbols-start 6340 composition ((1 32 65 57708)) fontified t) 6209 6214 (fontified t) 6214 6216 (face font-lock-doc-face fontified t) 6216 6217 (face font-lock-doc-face syntax-table (15) fontified t) 6217 6277 (face font-lock-doc-face fontified t) 6277 6278 (face font-lock-doc-face syntax-table (15) fontified t) 6278 6280 (face font-lock-doc-face fontified t) 6280 6290 (fontified t) 6290 6291 (prettify-symbols-end 6423 prettify-symbols-start 6422 composition ((1 32 65 57708)) fontified t) 6291 6292 (fontified t) 6292 6295 (face font-lock-builtin-face fontified t) 6295 6300 (fontified t) 6300 6302 (face font-lock-string-face fontified t) 6302 6303 (face font-lock-string-face syntax-table (15) fontified t) 6303 6339 (face font-lock-string-face fontified t) 6339 6340 (face font-lock-string-face syntax-table (15) fontified t) 6340 6342 (face font-lock-string-face fontified t) 6342 6353 (fontified t) 6353 6354 (prettify-symbols-end 6486 prettify-symbols-start 6485 composition ((1 32 65 57708)) fontified t) 6354 6355 (fontified t) 6355 6358 (face font-lock-builtin-face fontified t) 6358 6359 (fontified t) 6359 6360 (face font-lock-operator-face fontified t) 6360 6361 (fontified t) 6361 6365 (face font-lock-constant-face fontified t) 6365 6366 (fontified t) 6366 6367 (face font-lock-operator-face fontified t) 6367 6368 (fontified t) 6368 6372 (face font-lock-constant-face fontified t) 6372 6377 (fontified t) 6377 6379 (face font-lock-doc-face fontified t) 6379 6380 (face font-lock-doc-face syntax-table (15) fontified t) 6380 6715 (face font-lock-doc-face fontified t) 6715 6716 (face font-lock-doc-face syntax-table (15) fontified t) 6716 6718 (face font-lock-doc-face fontified t) 6718 6721 (fontified t) 6721 6726 (face font-lock-keyword-face fontified t) 6726 6727 (fontified t) 6727 6741 (face font-lock-type-face fontified t) 6741 6742 (face (rainbow-delimiters-depth-1-face) fontified t) 6742 6754 (fontified t) 6754 6755 (face (rainbow-delimiters-depth-1-face) fontified t) 6755 6756 (prettify-symbols-end 6888 prettify-symbols-start 6887 composition (0 1 [32 65 57708]) fontified t) 6756 6761 (fontified t) 6761 6763 (face font-lock-doc-face fontified t) 6763 6764 (face font-lock-doc-face syntax-table (15) fontified t) 6764 6820 (face font-lock-doc-face fontified t) 6820 6821 (face font-lock-doc-face syntax-table (15) fontified t) 6821 6823 (face font-lock-doc-face fontified t) 6823 6836 (fontified t) 6836 6837 (prettify-symbols-end 6969 prettify-symbols-start 6968 composition (0 1 [32 65 57708]) fontified t) 6837 6838 (fontified t) 6838 6841 (face font-lock-builtin-face fontified t) 6841 6846 (fontified t) 6846 6858 (face font-lock-variable-name-face fontified t) 6858 6859 (fontified t) 6859 6860 (face font-lock-operator-face fontified t) 6860 6871 (fontified t) 6871 6872 (face (rainbow-delimiters-depth-1-face) fontified t) 6872 6877 (fontified t) 6877 6878 (face font-lock-operator-face fontified t) 6878 6885 (face font-lock-string-face fontified t) 6885 6886 (face (rainbow-delimiters-depth-1-face) fontified t) 6886 6889 (fontified t) 6889 6894 (face font-lock-keyword-face fontified t) 6894 6895 (fontified t) 6895 6910 (face font-lock-type-face fontified t) 6910 6911 (face (rainbow-delimiters-depth-1-face) fontified t) 6911 6920 (fontified t) 6920 6921 (face (rainbow-delimiters-depth-1-face) fontified t) 6921 6922 (prettify-symbols-end 7054 prettify-symbols-start 7053 composition (0 1 [32 65 57708]) fontified t) 6922 6927 (fontified t) 6927 6929 (face font-lock-doc-face fontified t) 6929 6930 (face font-lock-doc-face syntax-table (15) fontified t) 6930 6961 (face font-lock-doc-face fontified t) 6961 6962 (face font-lock-doc-face syntax-table (15) fontified t) 6962 6964 (face font-lock-doc-face fontified t) 6964 6981 (fontified t) 6981 6982 (prettify-symbols-end 7114 prettify-symbols-start 7113 composition (0 1 [32 65 57708]) fontified t) 6982 6983 (fontified t) 6983 6987 (face font-lock-builtin-face fontified t) 6987 6988 (fontified t) 6988 6989 (face font-lock-operator-face fontified t) 6989 6990 (fontified t) 6990 6994 (face font-lock-constant-face fontified t) 6994 6995 (fontified t) 6995 6996 (face font-lock-operator-face fontified t) 6996 6997 (fontified t) 6997 7001 (face font-lock-constant-face fontified t) 7001 7006 (fontified t) 7006 7008 (face font-lock-doc-face fontified t) 7008 7009 (face font-lock-doc-face syntax-table (15) fontified t) 7009 7081 (face font-lock-doc-face fontified t) 7081 7082 (face font-lock-doc-face syntax-table (15) fontified t) 7082 7084 (face font-lock-doc-face fontified t) 7084 7089 (fontified t) 7089 7101 (face font-lock-variable-name-face fontified t) 7101 7102 (fontified t) 7102 7103 (face font-lock-operator-face fontified t) 7103 7114 (fontified t) 7114 7115 (face (rainbow-delimiters-depth-1-face) fontified t) 7115 7120 (fontified t) 7120 7121 (face font-lock-operator-face fontified t) 7121 7128 (face font-lock-string-face fontified t) 7128 7129 (face (rainbow-delimiters-depth-1-face) fontified t) 7129 7132 (fontified t) 7132 7137 (face font-lock-keyword-face fontified t) 7137 7138 (fontified t) 7138 7156 (face font-lock-type-face fontified t) 7156 7157 (face (rainbow-delimiters-depth-1-face) fontified t) 7157 7166 (fontified t) 7166 7167 (face (rainbow-delimiters-depth-1-face) fontified t) 7167 7168 (prettify-symbols-end 7300 prettify-symbols-start 7299 composition (0 1 [32 65 57708]) fontified t) 7168 7173 (fontified t) 7173 7175 (face font-lock-doc-face fontified t) 7175 7176 (face font-lock-doc-face syntax-table (15) fontified t) 7176 7211 (face font-lock-doc-face fontified t) 7211 7212 (face font-lock-doc-face syntax-table (15) fontified t) 7212 7214 (face font-lock-doc-face fontified t) 7214 7220 (fontified t) 7220 7232 (face font-lock-variable-name-face fontified t) 7232 7233 (fontified t) 7233 7234 (face font-lock-operator-face fontified t) 7234 7245 (fontified t) 7245 7246 (face (rainbow-delimiters-depth-1-face) fontified t) 7246 7251 (fontified t) 7251 7252 (face font-lock-operator-face fontified t) 7252 7259 (face font-lock-string-face fontified t) 7259 7260 (face (rainbow-delimiters-depth-1-face) fontified t) 7260 7263 (fontified t) 7263 7268 (face font-lock-keyword-face fontified t) 7268 7269 (fontified t) 7269 7290 (face font-lock-type-face fontified t) 7290 7291 (face (rainbow-delimiters-depth-1-face) fontified t) 7291 7300 (fontified t) 7300 7301 (face (rainbow-delimiters-depth-1-face) fontified t) 7301 7302 (prettify-symbols-end 7434 prettify-symbols-start 7433 composition (0 1 [32 65 57708]) fontified t) 7302 7307 (fontified t) 7307 7309 (face font-lock-doc-face fontified t) 7309 7310 (face font-lock-doc-face syntax-table (15) fontified t) 7310 7348 (face font-lock-doc-face fontified t) 7348 7349 (face font-lock-doc-face syntax-table (15) fontified t) 7349 7351 (face font-lock-doc-face fontified t) 7351 7357 (fontified t) 7357 7369 (face font-lock-variable-name-face fontified t) 7369 7370 (fontified t) 7370 7371 (face font-lock-operator-face fontified t) 7371 7382 (fontified t) 7382 7383 (face (rainbow-delimiters-depth-1-face) fontified t) 7383 7388 (fontified t) 7388 7389 (face font-lock-operator-face fontified t) 7389 7396 (face font-lock-string-face fontified t) 7396 7397 (face (rainbow-delimiters-depth-1-face) fontified t) 7397 7400 (fontified t) 7400 7405 (face font-lock-keyword-face fontified t) 7405 7406 (fontified t) 7406 7424 (face font-lock-type-face fontified t) 7424 7425 (face (rainbow-delimiters-depth-1-face) fontified t) 7425 7434 (fontified t) 7434 7435 (face (rainbow-delimiters-depth-1-face) fontified t) 7435 7436 (prettify-symbols-end 7568 prettify-symbols-start 7567 composition (0 1 [32 65 57708]) fontified t) 7436 7441 (fontified t) 7441 7443 (face font-lock-doc-face fontified t) 7443 7444 (face font-lock-doc-face syntax-table (15) fontified t) 7444 7478 (face font-lock-doc-face fontified t) 7478 7479 (face font-lock-doc-face syntax-table (15) fontified t) 7479 7481 (face font-lock-doc-face fontified t) 7481 7499 (fontified t) 7499 7500 (prettify-symbols-end 7632 prettify-symbols-start 7631 composition (0 1 [32 65 57708]) fontified t) 7500 7501 (fontified t) 7501 7505 (face font-lock-builtin-face fontified t) 7505 7506 (face (rainbow-delimiters-depth-1-face) fontified t) 7506 7509 (face font-lock-builtin-face fontified t) 7509 7511 (fontified t) 7511 7515 (face font-lock-builtin-face fontified t) 7515 7516 (face (rainbow-delimiters-depth-2-face) fontified t) 7516 7519 (face font-lock-builtin-face fontified t) 7519 7524 (fontified t) 7524 7525 (face (rainbow-delimiters-depth-2-face) fontified t) 7525 7526 (face (rainbow-delimiters-depth-1-face) fontified t) 7526 7527 (fontified t) 7527 7528 (face font-lock-operator-face fontified t) 7528 7529 (fontified t) 7529 7533 (face font-lock-constant-face fontified t) 7533 7534 (fontified t) 7534 7535 (face font-lock-operator-face fontified t) 7535 7536 (fontified t) 7536 7540 (face font-lock-constant-face fontified t) 7540 7545 (fontified t) 7545 7547 (face font-lock-doc-face fontified t) 7547 7548 (face font-lock-doc-face syntax-table (15) fontified t) 7548 7613 (face font-lock-doc-face fontified t) 7613 7614 (face font-lock-doc-face syntax-table (15) fontified t) 7614 7616 (face font-lock-doc-face fontified t) 7616 7629 (fontified t) 7629 7630 (prettify-symbols-end 7762 prettify-symbols-start 7761 composition (0 1 [32 65 57708]) fontified t) 7630 7650 (fontified t) 7650 7651 (face font-lock-operator-face fontified t) 7651 7652 (fontified t) 7652 7656 (face font-lock-constant-face fontified t) 7656 7657 (fontified t) 7657 7658 (face font-lock-operator-face fontified t) 7658 7659 (fontified t) 7659 7663 (face font-lock-constant-face fontified t) 7663 7668 (fontified t) 7668 7670 (face font-lock-doc-face fontified t) 7670 7671 (face font-lock-doc-face syntax-table (15) fontified t) 7671 7723 (face font-lock-doc-face fontified t) 7723 7724 (face font-lock-doc-face syntax-table (15) fontified t) 7724 7726 (face font-lock-doc-face fontified t) 7726 7742 (fontified t) 7742 7743 (prettify-symbols-end 7875 prettify-symbols-start 7874 composition (0 1 [32 65 57708]) fontified t) 7743 7766 (fontified t) 7766 7767 (face font-lock-operator-face fontified t) 7767 7768 (fontified t) 7768 7772 (face font-lock-constant-face fontified t) 7772 7773 (fontified t) 7773 7774 (face font-lock-operator-face fontified t) 7774 7775 (fontified t) 7775 7779 (face font-lock-constant-face fontified t) 7779 7784 (fontified t) 7784 7786 (face font-lock-doc-face fontified t) 7786 7787 (face font-lock-doc-face syntax-table (15) fontified t) 7787 7844 (face font-lock-doc-face fontified t) 7844 7845 (face font-lock-doc-face syntax-table (15) fontified t) 7845 7847 (face font-lock-doc-face fontified t) 7847 7857 (fontified t) 7857 7858 (prettify-symbols-end 7990 prettify-symbols-start 7989 composition (0 1 [32 65 57708]) fontified t) 7858 7875 (fontified t) 7875 7876 (face font-lock-operator-face fontified t) 7876 7877 (fontified t) 7877 7881 (face font-lock-constant-face fontified t) 7881 7882 (fontified t) 7882 7883 (face font-lock-operator-face fontified t) 7883 7884 (fontified t) 7884 7888 (face font-lock-constant-face fontified t) 7888 7893 (fontified t) 7893 7895 (face font-lock-doc-face fontified t) 7895 7896 (face font-lock-doc-face syntax-table (15) fontified t) 7896 7941 (face font-lock-doc-face fontified t) 7941 7942 (face font-lock-doc-face syntax-table (15) fontified t) 7942 7944 (face font-lock-doc-face fontified t) 7944 7949 (fontified t) 7949 7961 (face font-lock-variable-name-face fontified t) 7961 7962 (fontified t) 7962 7963 (face font-lock-operator-face fontified t) 7963 7974 (fontified t) 7974 7975 (face (rainbow-delimiters-depth-1-face) fontified t) 7975 7980 (fontified t) 7980 7981 (face font-lock-operator-face fontified t) 7981 7988 (face font-lock-string-face fontified t) 7988 7989 (face (rainbow-delimiters-depth-1-face) fontified t) 7989 7992 (fontified t) 7992 7997 (face font-lock-keyword-face fontified t) 7997 7998 (fontified t) 7998 8015 (face font-lock-type-face fontified t) 8015 8016 (face (rainbow-delimiters-depth-1-face) fontified t) 8016 8025 (fontified t) 8025 8026 (face (rainbow-delimiters-depth-1-face) fontified t) 8026 8027 (prettify-symbols-end 8159 prettify-symbols-start 8158 composition (0 1 [32 65 57708]) fontified t) 8027 8032 (fontified t) 8032 8034 (face font-lock-doc-face fontified t) 8034 8035 (face font-lock-doc-face syntax-table (15) fontified t) 8035 8069 (face font-lock-doc-face fontified t) 8069 8070 (face font-lock-doc-face syntax-table (15) fontified t) 8070 8072 (face font-lock-doc-face fontified t) 8072 8089 (fontified t) 8089 8090 (prettify-symbols-end 8222 prettify-symbols-start 8221 composition (0 1 [32 65 57708]) fontified t) 8090 8091 (fontified t) 8091 8095 (face font-lock-builtin-face fontified t) 8095 8096 (fontified t) 8096 8097 (face font-lock-operator-face fontified t) 8097 8098 (fontified t) 8098 8102 (face font-lock-constant-face fontified t) 8102 8103 (fontified t) 8103 8104 (face font-lock-operator-face fontified t) 8104 8105 (fontified t) 8105 8109 (face font-lock-constant-face fontified t) 8109 8114 (fontified t) 8114 8116 (face font-lock-doc-face fontified t) 8116 8117 (face font-lock-doc-face syntax-table (15) fontified t) 8117 8191 (face font-lock-doc-face fontified t) 8191 8192 (face font-lock-doc-face syntax-table (15) fontified t) 8192 8194 (face font-lock-doc-face fontified t) 8194 8199 (fontified t) 8199 8211 (face font-lock-variable-name-face fontified t) 8211 8212 (fontified t) 8212 8213 (face font-lock-operator-face fontified t) 8213 8224 (fontified t) 8224 8225 (face (rainbow-delimiters-depth-1-face) fontified t) 8225 8230 (fontified t) 8230 8231 (face font-lock-operator-face fontified t) 8231 8238 (face font-lock-string-face fontified t) 8238 8239 (face (rainbow-delimiters-depth-1-face) fontified t) 8239 8242 (fontified t) 8242 8247 (face font-lock-keyword-face fontified t) 8247 8248 (fontified t) 8248 8267 (face font-lock-type-face fontified t) 8267 8268 (face (rainbow-delimiters-depth-1-face) fontified t) 8268 8277 (fontified t) 8277 8278 (face (rainbow-delimiters-depth-1-face) fontified t) 8278 8279 (prettify-symbols-end 8411 prettify-symbols-start 8410 composition (0 1 [32 65 57708]) fontified t) 8279 8284 (fontified t) 8284 8286 (face font-lock-doc-face fontified t) 8286 8287 (face font-lock-doc-face syntax-table (15) fontified t) 8287 8323 (face font-lock-doc-face fontified t) 8323 8324 (face font-lock-doc-face syntax-table (15) fontified t) 8324 8326 (face font-lock-doc-face fontified t) 8326 8341 (fontified t) 8341 8342 (prettify-symbols-end 8474 prettify-symbols-start 8473 composition (0 1 [32 65 57708]) fontified t) 8342 8343 (fontified t) 8343 8347 (face font-lock-builtin-face fontified t) 8347 8348 (fontified t) 8348 8349 (face font-lock-operator-face fontified t) 8349 8350 (fontified t) 8350 8354 (face font-lock-constant-face fontified t) 8354 8355 (fontified t) 8355 8356 (face font-lock-operator-face fontified t) 8356 8357 (fontified t) 8357 8361 (face font-lock-constant-face fontified t) 8361 8366 (fontified t) 8366 8368 (face font-lock-doc-face fontified t) 8368 8369 (face font-lock-doc-face syntax-table (15) fontified t) 8369 8430 (face font-lock-doc-face fontified t) 8430 8431 (face font-lock-doc-face syntax-table (15) fontified t) 8431 8433 (face font-lock-doc-face fontified t) 8433 8449 (fontified t) 8449 8450 (prettify-symbols-end 8582 prettify-symbols-start 8581 composition (0 1 [32 65 57708]) fontified t) 8450 8451 (fontified t) 8451 8455 (face font-lock-builtin-face fontified t) 8455 8456 (fontified t) 8456 8457 (face font-lock-operator-face fontified t) 8457 8458 (fontified t) 8458 8462 (face font-lock-constant-face fontified t) 8462 8463 (fontified t) 8463 8464 (face font-lock-operator-face fontified t) 8464 8465 (fontified t) 8465 8469 (face font-lock-constant-face fontified t) 8469 8474 (fontified t) 8474 8476 (face font-lock-doc-face fontified t) 8476 8477 (face font-lock-doc-face syntax-table (15) fontified t) 8477 8553 (face font-lock-doc-face fontified t) 8553 8554 (face font-lock-doc-face syntax-table (15) fontified t) 8554 8556 (face font-lock-doc-face fontified t) 8556 8561 (fontified t) 8561 8573 (face font-lock-variable-name-face fontified t) 8573 8574 (fontified t) 8574 8575 (face font-lock-operator-face fontified t) 8575 8586 (fontified t) 8586 8587 (face (rainbow-delimiters-depth-1-face) fontified t) 8587 8592 (fontified t) 8592 8593 (face font-lock-operator-face fontified t) 8593 8600 (face font-lock-string-face fontified t) 8600 8601 (face (rainbow-delimiters-depth-1-face) fontified t) 8601 8604 (fontified t) 8604 8609 (face font-lock-keyword-face fontified t) 8609 8610 (fontified t) 8610 8625 (face font-lock-type-face fontified t) 8625 8626 (face (rainbow-delimiters-depth-1-face) fontified t) 8626 8635 (fontified t) 8635 8636 (face (rainbow-delimiters-depth-1-face) fontified t) 8636 8637 (prettify-symbols-end 8769 prettify-symbols-start 8768 composition (0 1 [32 65 57708]) fontified t) 8637 8642 (fontified t) 8642 8644 (face font-lock-doc-face fontified t) 8644 8645 (face font-lock-doc-face syntax-table (15) fontified t) 8645 8677 (face font-lock-doc-face fontified t) 8677 8678 (face font-lock-doc-face syntax-table (15) fontified t) 8678 8680 (face font-lock-doc-face fontified t) 8680 8697 (fontified t) 8697 8698 (prettify-symbols-end 8830 prettify-symbols-start 8829 composition ((1 32 65 57708)) fontified t) 8698 8699 (fontified t) 8699 8703 (face font-lock-builtin-face fontified t) 8703 8704 (fontified t) 8704 8705 (face font-lock-operator-face fontified t) 8705 8706 (fontified t) 8706 8710 (face font-lock-constant-face fontified t) 8710 8711 (fontified t) 8711 8712 (face font-lock-operator-face fontified t) 8712 8713 (fontified t) 8713 8717 (face font-lock-constant-face fontified t) 8717 8722 (fontified t) 8722 8724 (face font-lock-doc-face fontified t) 8724 8725 (face font-lock-doc-face syntax-table (15) fontified t) 8725 8797 (face font-lock-doc-face fontified t) 8797 8798 (face font-lock-doc-face syntax-table (15) fontified t) 8798 8800 (face font-lock-doc-face fontified t) 8800 8805 (fontified t) 8805 8817 (face font-lock-variable-name-face fontified t) 8817 8818 (fontified t) 8818 8819 (face font-lock-operator-face fontified t) 8819 8830 (fontified t) 8830 8831 (face (rainbow-delimiters-depth-1-face) fontified t) 8831 8836 (fontified t) 8836 8837 (face font-lock-operator-face fontified t) 8837 8844 (face font-lock-string-face fontified t) 8844 8845 (face (rainbow-delimiters-depth-1-face) fontified t) 8845 8848 (fontified t) 8848 8853 (face font-lock-keyword-face fontified t) 8853 8854 (fontified t) 8854 8871 (face font-lock-type-face fontified t) 8871 8872 (face (rainbow-delimiters-depth-1-face) fontified t) 8872 8881 (fontified t) 8881 8882 (face (rainbow-delimiters-depth-1-face) fontified t) 8882 8883 (prettify-symbols-end 9015 prettify-symbols-start 9014 composition (0 1 [32 65 57708]) fontified t) 8883 8888 (fontified t) 8888 8890 (face font-lock-doc-face fontified t) 8890 8891 (face font-lock-doc-face syntax-table (15) fontified t) 8891 8925 (face font-lock-doc-face fontified t) 8925 8926 (face font-lock-doc-face syntax-table (15) fontified t) 8926 8928 (face font-lock-doc-face fontified t) 8928 8934 (fontified t) 8934 8946 (face font-lock-variable-name-face fontified t) 8946 8947 (fontified t) 8947 8948 (face font-lock-operator-face fontified t) 8948 8959 (fontified t) 8959 8960 (face (rainbow-delimiters-depth-1-face) fontified t) 8960 8965 (fontified t) 8965 8966 (face font-lock-operator-face fontified t) 8966 8973 (face font-lock-string-face fontified t) 8973 8974 (face (rainbow-delimiters-depth-1-face) fontified t) 8974 8977 (fontified t) 8977 8982 (face font-lock-keyword-face fontified t) 8982 8983 (fontified t) 8983 9004 (face font-lock-type-face fontified t) 9004 9005 (face (rainbow-delimiters-depth-1-face) fontified t) 9005 9014 (fontified t) 9014 9015 (face (rainbow-delimiters-depth-1-face) fontified t) 9015 9016 (prettify-symbols-end 9148 prettify-symbols-start 9147 composition (0 1 [32 65 57708]) fontified t) 9016 9021 (fontified t) 9021 9023 (face font-lock-doc-face fontified t) 9023 9024 (face font-lock-doc-face syntax-table (15) fontified t) 9024 9062 (face font-lock-doc-face fontified t) 9062 9063 (face font-lock-doc-face syntax-table (15) fontified t) 9063 9065 (face font-lock-doc-face fontified t) 9065 9071 (fontified t) 9071 9083 (face font-lock-variable-name-face fontified t) 9083 9084 (fontified t) 9084 9085 (face font-lock-operator-face fontified t) 9085 9096 (fontified t) 9096 9097 (face (rainbow-delimiters-depth-1-face) fontified t) 9097 9102 (fontified t) 9102 9103 (face font-lock-operator-face fontified t) 9103 9110 (face font-lock-string-face fontified t) 9110 9111 (face (rainbow-delimiters-depth-1-face) fontified t) 9111 9114 (fontified t) 9114 9119 (face font-lock-keyword-face fontified t) 9119 9120 (fontified t) 9120 9138 (face font-lock-type-face fontified t) 9138 9139 (face (rainbow-delimiters-depth-1-face) fontified t) 9139 9148 (fontified t) 9148 9149 (face (rainbow-delimiters-depth-1-face) fontified t) 9149 9150 (prettify-symbols-end 9282 prettify-symbols-start 9281 composition (0 1 [32 65 57708]) fontified t) 9150 9155 (fontified t) 9155 9157 (face font-lock-doc-face fontified t) 9157 9158 (face font-lock-doc-face syntax-table (15) fontified t) 9158 9197 (face font-lock-doc-face fontified t) 9197 9198 (face font-lock-doc-face syntax-table (15) fontified t) 9198 9200 (face font-lock-doc-face fontified t) 9200 9218 (fontified t) 9218 9219 (prettify-symbols-end 9351 prettify-symbols-start 9350 composition (0 1 [32 65 57708]) fontified t) 9219 9220 (fontified t) 9220 9224 (face font-lock-builtin-face fontified t) 9224 9225 (face (rainbow-delimiters-depth-1-face) fontified t) 9225 9228 (face font-lock-builtin-face fontified t) 9228 9230 (fontified t) 9230 9234 (face font-lock-builtin-face fontified t) 9234 9235 (face (rainbow-delimiters-depth-2-face) fontified t) 9235 9238 (face font-lock-builtin-face fontified t) 9238 9243 (fontified t) 9243 9244 (face (rainbow-delimiters-depth-2-face) fontified t) 9244 9245 (face (rainbow-delimiters-depth-1-face) fontified t) 9245 9246 (fontified t) 9246 9247 (face font-lock-operator-face fontified t) 9247 9248 (fontified t) 9248 9252 (face font-lock-constant-face fontified t) 9252 9253 (fontified t) 9253 9254 (face font-lock-operator-face fontified t) 9254 9255 (fontified t) 9255 9259 (face font-lock-constant-face fontified t) 9259 9264 (fontified t) 9264 9266 (face font-lock-doc-face fontified t) 9266 9267 (face font-lock-doc-face syntax-table (15) fontified t) 9267 9332 (face font-lock-doc-face fontified t) 9332 9333 (face font-lock-doc-face syntax-table (15) fontified t) 9333 9335 (face font-lock-doc-face fontified t) 9335 9347 (fontified t) 9347 9348 (prettify-symbols-end 9480 prettify-symbols-start 9479 composition (0 1 [32 65 57708]) fontified t) 9348 9367 (fontified t) 9367 9368 (face font-lock-operator-face fontified t) 9368 9369 (fontified t) 9369 9373 (face font-lock-constant-face fontified t) 9373 9374 (fontified t) 9374 9375 (face font-lock-operator-face fontified t) 9375 9376 (fontified t) 9376 9380 (face font-lock-constant-face fontified t) 9380 9385 (fontified t) 9385 9387 (face font-lock-doc-face fontified t) 9387 9388 (face font-lock-doc-face syntax-table (15) fontified t) 9388 9454 (face font-lock-doc-face fontified t) 9454 9455 (face font-lock-doc-face syntax-table (15) fontified t) 9455 9457 (face font-lock-doc-face fontified t) 9457 9469 (fontified t) 9469 9470 (prettify-symbols-end 9602 prettify-symbols-start 9601 composition (0 1 [32 65 57708]) fontified t) 9470 9489 (fontified t) 9489 9490 (face font-lock-operator-face fontified t) 9490 9491 (fontified t) 9491 9495 (face font-lock-constant-face fontified t) 9495 9496 (fontified t) 9496 9497 (face font-lock-operator-face fontified t) 9497 9498 (fontified t) 9498 9502 (face font-lock-constant-face fontified t) 9502 9507 (fontified t) 9507 9509 (face font-lock-doc-face fontified t) 9509 9510 (face font-lock-doc-face syntax-table (15) fontified t) 9510 9560 (face font-lock-doc-face fontified t) 9560 9561 (face font-lock-doc-face syntax-table (15) fontified t) 9561 9563 (face font-lock-doc-face fontified t) 9563 9577 (fontified t) 9577 9578 (prettify-symbols-end 9710 prettify-symbols-start 9709 composition (0 1 [32 65 57708]) fontified t) 9578 9599 (fontified t) 9599 9600 (face font-lock-operator-face fontified t) 9600 9601 (fontified t) 9601 9605 (face font-lock-constant-face fontified t) 9605 9606 (fontified t) 9606 9607 (face font-lock-operator-face fontified t) 9607 9608 (fontified t) 9608 9612 (face font-lock-constant-face fontified t) 9612 9617 (fontified t) 9617 9619 (face font-lock-doc-face fontified t) 9619 9620 (face font-lock-doc-face syntax-table (15) fontified t) 9620 9671 (face font-lock-doc-face fontified t) 9671 9672 (face font-lock-doc-face syntax-table (15) fontified t) 9672 9674 (face font-lock-doc-face fontified t) 9674 9684 (fontified t) 9684 9685 (prettify-symbols-end 9817 prettify-symbols-start 9816 composition (0 1 [32 65 57708]) fontified t) 9685 9702 (fontified t) 9702 9703 (face font-lock-operator-face fontified t) 9703 9704 (fontified t) 9704 9708 (face font-lock-constant-face fontified t) 9708 9709 (fontified t) 9709 9710 (face font-lock-operator-face fontified t) 9710 9711 (fontified t) 9711 9715 (face font-lock-constant-face fontified t) 9715 9720 (fontified t) 9720 9722 (face font-lock-doc-face fontified t) 9722 9723 (face font-lock-doc-face syntax-table (15) fontified t) 9723 9770 (face font-lock-doc-face fontified t) 9770 9771 (face font-lock-doc-face syntax-table (15) fontified t) 9771 9773 (face font-lock-doc-face fontified t) 9773 9789 (fontified t) 9789 9790 (prettify-symbols-end 9922 prettify-symbols-start 9921 composition (0 1 [32 65 57708]) fontified t) 9790 9813 (fontified t) 9813 9814 (face font-lock-operator-face fontified t) 9814 9815 (fontified t) 9815 9819 (face font-lock-constant-face fontified t) 9819 9820 (fontified t) 9820 9821 (face font-lock-operator-face fontified t) 9821 9822 (fontified t) 9822 9826 (face font-lock-constant-face fontified t) 9826 9831 (fontified t) 9831 9833 (face font-lock-doc-face fontified t) 9833 9834 (face font-lock-doc-face syntax-table (15) fontified t) 9834 9916 (face font-lock-doc-face fontified t) 9916 9917 (face font-lock-doc-face syntax-table (15) fontified t) 9917 9919 (face font-lock-doc-face fontified t) 9919 9924 (fontified t) 9924 9936 (face font-lock-variable-name-face fontified t) 9936 9937 (fontified t) 9937 9938 (face font-lock-operator-face fontified t) 9938 9949 (fontified t) 9949 9950 (face (rainbow-delimiters-depth-1-face) fontified t) 9950 9955 (fontified t) 9955 9956 (face font-lock-operator-face fontified t) 9956 9963 (face font-lock-string-face fontified t) 9963 9964 (face (rainbow-delimiters-depth-1-face) fontified t) 9964 9967 (fontified t) 9967 9972 (face font-lock-keyword-face fontified t) 9972 9973 (fontified t) 9973 9996 (face font-lock-type-face fontified t) 9996 9997 (face (rainbow-delimiters-depth-1-face) fontified t) 9997 10010 (fontified t) 10010 10011 (face (rainbow-delimiters-depth-1-face) fontified t) 10011 10012 (prettify-symbols-end 10144 prettify-symbols-start 10143 composition (0 1 [32 65 57708]) fontified t) 10012 10017 (fontified t) 10017 10019 (face font-lock-doc-face fontified t) 10019 10020 (face font-lock-doc-face syntax-table (15) fontified t) 10020 10058 (face font-lock-doc-face fontified t) 10058 10059 (face font-lock-doc-face syntax-table (15) fontified t) 10059 10061 (face font-lock-doc-face fontified t) 10061 10082 (fontified t) 10082 10083 (prettify-symbols-end 10215 prettify-symbols-start 10214 composition (0 1 [32 65 57708]) fontified t) 10083 10084 (fontified t) 10084 10087 (face font-lock-builtin-face fontified t) 10087 10088 (fontified t) 10088 10089 (face font-lock-operator-face fontified t) 10089 10090 (fontified t) 10090 10093 (face font-lock-builtin-face fontified t) 10093 10098 (fontified t) 10098 10100 (face font-lock-string-face fontified t) 10100 10101 (face font-lock-string-face syntax-table (15) fontified t) 10101 10175 (face font-lock-string-face fontified t) 10175 10176 (face font-lock-string-face syntax-table (15) fontified t) 10176 10178 (face font-lock-string-face fontified t) 10178 10195 (fontified t) 10195 10196 (prettify-symbols-end 10328 prettify-symbols-start 10327 composition (0 1 [32 65 57708]) fontified t) 10196 10230 (fontified t) 10230 10231 (prettify-symbols-end 10363 prettify-symbols-start 10362 composition (0 1 [32 65 57708]) fontified t) 10231 10251 (fontified t) 10251 10263 (face font-lock-variable-name-face fontified t) 10263 10264 (fontified t) 10264 10265 (face font-lock-operator-face fontified t) 10265 10276 (fontified t) 10276 10277 (face (rainbow-delimiters-depth-1-face) fontified t) 10277 10282 (fontified t) 10282 10283 (face font-lock-operator-face fontified t) 10283 10290 (face font-lock-string-face fontified t) 10290 10291 (face (rainbow-delimiters-depth-1-face) fontified t) 10291 10294 (fontified t) 10294 10299 (face font-lock-keyword-face fontified t) 10299 10300 (fontified t) 10300 10317 (face font-lock-type-face fontified t) 10317 10318 (face (rainbow-delimiters-depth-1-face) fontified t) 10318 10325 (fontified t) 10325 10326 (face (rainbow-delimiters-depth-2-face) fontified t) 10326 10358 (fontified t) 10358 10359 (face (rainbow-delimiters-depth-3-face) fontified t) 10359 10371 (face font-lock-string-face fontified t) 10371 10372 (face (rainbow-delimiters-depth-3-face) fontified t) 10372 10373 (face (rainbow-delimiters-depth-2-face) fontified t) 10373 10374 (face (rainbow-delimiters-depth-1-face) fontified t) 10374 10375 (prettify-symbols-end 10507 prettify-symbols-start 10506 composition (0 1 [32 65 57708]) fontified t) 10375 10380 (fontified t) 10380 10382 (face font-lock-doc-face fontified t) 10382 10383 (face font-lock-doc-face syntax-table (15) fontified t) 10383 10506 (face font-lock-doc-face fontified t) 10506 10507 (face font-lock-doc-face syntax-table (15) fontified t) 10507 10509 (face font-lock-doc-face fontified t) 10509 10521 (fontified t) 10521 10522 (prettify-symbols-end 10654 prettify-symbols-start 10653 composition (0 1 [32 65 57708]) fontified t) 10522 10530 (fontified t) 10530 10531 (face (rainbow-delimiters-depth-1-face) fontified t) 10531 10543 (face font-lock-string-face fontified t) 10543 10544 (face (rainbow-delimiters-depth-1-face) fontified t) 10544 10555 (fontified t) 10555 10556 (prettify-symbols-end 10688 prettify-symbols-start 10687 composition (0 1 [32 65 57708]) fontified t) 10556 10583 (fontified t) 10583 10588 (face font-lock-keyword-face fontified t) 10588 10589 (fontified t) 10589 10605 (face font-lock-type-face fontified t) 10605 10606 (face (rainbow-delimiters-depth-1-face) fontified t) 10606 10612 (fontified t) 10612 10613 (face (rainbow-delimiters-depth-1-face) fontified t) 10613 10614 (prettify-symbols-end 10746 prettify-symbols-start 10745 composition (0 1 [32 65 57708]) fontified t) 10614 10619 (fontified t) 10619 10621 (face font-lock-doc-face fontified t) 10621 10622 (face font-lock-doc-face syntax-table (15) fontified t) 10622 10699 (face font-lock-doc-face fontified t) 10699 10700 (face font-lock-doc-face syntax-table (15) fontified t) 10700 10702 (face font-lock-doc-face fontified t) 10702 10723 (fontified t) 10723 10724 (prettify-symbols-end 10856 prettify-symbols-start 10855 composition (0 1 [32 65 57708]) fontified t) 10724 10725 (fontified t) 10725 10728 (face font-lock-builtin-face fontified t) 10728 10729 (fontified t) 10729 10730 (face font-lock-operator-face fontified t) 10730 10731 (fontified t) 10731 10734 (face font-lock-builtin-face fontified t) 10734 10739 (fontified t) 10739 10741 (face font-lock-string-face fontified t) 10741 10742 (face font-lock-string-face syntax-table (15) fontified t) 10742 10813 (face font-lock-string-face fontified t) 10813 10814 (face font-lock-string-face syntax-table (15) fontified t) 10814 10816 (face font-lock-string-face fontified t) 10816 10833 (fontified t) 10833 10834 (prettify-symbols-end 10966 prettify-symbols-start 10965 composition (0 1 [32 65 57708]) fontified t) 10834 10868 (fontified t) 10868 10869 (prettify-symbols-end 11001 prettify-symbols-start 11000 composition (0 1 [32 65 57708]) fontified t) 10869 10901 (fontified t) 10901 10902 (prettify-symbols-end 11034 prettify-symbols-start 11033 composition (0 1 [32 65 57708]) fontified t) 10902 10903 (fontified t) 10903 10906 (face font-lock-builtin-face fontified t) 10906 10907 (fontified t) 10907 10908 (face font-lock-operator-face fontified t) 10908 10909 (fontified t) 10909 10913 (face font-lock-constant-face fontified t) 10913 10914 (fontified t) 10914 10915 (face font-lock-operator-face fontified t) 10915 10916 (fontified t) 10916 10920 (face font-lock-constant-face fontified t) 10920 10925 (fontified t) 10925 10927 (face font-lock-doc-face fontified t) 10927 10928 (face font-lock-doc-face syntax-table (15) fontified t) 10928 10991 (face font-lock-doc-face fontified t) 10991 10992 (face font-lock-doc-face syntax-table (15) fontified t) 10992 10994 (face font-lock-doc-face fontified t) 10994 10997 (fontified t) 10997 11002 (face font-lock-keyword-face fontified t) 11002 11003 (fontified t) 11003 11026 (face font-lock-type-face fontified t) 11026 11027 (face (rainbow-delimiters-depth-1-face) fontified t) 11027 11039 (fontified t) 11039 11040 (face (rainbow-delimiters-depth-2-face) fontified t) 11040 11059 (fontified t) 11059 11060 (face font-lock-operator-face fontified t) 11060 11061 (fontified t) 11061 11065 (face font-lock-constant-face fontified t) 11065 11074 (fontified t) 11074 11075 (face (rainbow-delimiters-depth-3-face) fontified t) 11075 11102 (face font-lock-string-face fontified t) 11102 11103 (face (rainbow-delimiters-depth-3-face) fontified t) 11103 11104 (face (rainbow-delimiters-depth-2-face) fontified t) 11104 11105 (face (rainbow-delimiters-depth-1-face) fontified t) 11105 11106 (prettify-symbols-end 11238 prettify-symbols-start 11237 composition (0 1 [32 65 57708]) fontified t) 11106 11111 (fontified t) 11111 11113 (face font-lock-doc-face fontified t) 11113 11114 (face font-lock-doc-face syntax-table (15) fontified t) 11114 11218 (face font-lock-doc-face fontified t) 11218 11219 (face font-lock-doc-face syntax-table (15) fontified t) 11219 11221 (face font-lock-doc-face fontified t) 11221 11233 (fontified t) 11233 11234 (prettify-symbols-end 11366 prettify-symbols-start 11365 composition (0 1 [32 65 57708]) fontified t) 11234 11242 (fontified t) 11242 11243 (face (rainbow-delimiters-depth-1-face) fontified t) 11243 11270 (face font-lock-string-face fontified t) 11270 11271 (face (rainbow-delimiters-depth-1-face) fontified t) 11271 11282 (fontified t) 11282 11283 (prettify-symbols-end 11415 prettify-symbols-start 11414 composition (0 1 [32 65 57708]) fontified t) 11283 11303 (fontified t) 11303 11304 (face font-lock-operator-face fontified t) 11304 11305 (fontified t) 11305 11309 (face font-lock-constant-face fontified t) 11309 11310 (fontified t) 11310 11311 (face font-lock-operator-face fontified t) 11311 11312 (fontified t) 11312 11316 (face font-lock-constant-face fontified t) 11316 11319 (fontified t) 11319 11324 (face font-lock-keyword-face fontified t) 11324 11325 (fontified t) 11325 11336 (face font-lock-type-face fontified t) 11336 11337 (face (rainbow-delimiters-depth-1-face) fontified t) 11337 11344 (fontified t) 11344 11345 (face (rainbow-delimiters-depth-2-face) fontified t) 11345 11359 (fontified t) 11359 11360 (face font-lock-operator-face fontified t) 11360 11361 (fontified t) 11361 11365 (face font-lock-constant-face fontified t) 11365 11374 (fontified t) 11374 11375 (face (rainbow-delimiters-depth-3-face) fontified t) 11375 11381 (face font-lock-string-face fontified t) 11381 11382 (face (rainbow-delimiters-depth-3-face) fontified t) 11382 11383 (face (rainbow-delimiters-depth-2-face) fontified t) 11383 11384 (face (rainbow-delimiters-depth-1-face) fontified t) 11384 11385 (prettify-symbols-end 11517 prettify-symbols-start 11516 composition (0 1 [32 65 57708]) fontified t) 11385 11390 (fontified t) 11390 11392 (face font-lock-doc-face fontified t) 11392 11393 (face font-lock-doc-face syntax-table (15) fontified t) 11393 11503 (face font-lock-doc-face fontified t) 11503 11504 (face font-lock-doc-face syntax-table (15) fontified t) 11504 11506 (face font-lock-doc-face fontified t) 11506 11518 (fontified t) 11518 11519 (prettify-symbols-end 11651 prettify-symbols-start 11650 composition (0 1 [32 65 57708]) fontified t) 11519 11527 (fontified t) 11527 11528 (face (rainbow-delimiters-depth-1-face) fontified t) 11528 11534 (face font-lock-string-face fontified t) 11534 11535 (face (rainbow-delimiters-depth-1-face) fontified t) 11535 11546 (fontified t) 11546 11547 (prettify-symbols-end 11679 prettify-symbols-start 11678 composition (0 1 [32 65 57708]) fontified t) 11547 11562 (fontified t) 11562 11563 (face font-lock-operator-face fontified t) 11563 11564 (fontified t) 11564 11568 (face font-lock-constant-face fontified t) 11568 11569 (fontified t) 11569 11570 (face font-lock-operator-face fontified t) 11570 11571 (fontified t) 11571 11575 (face font-lock-constant-face fontified t) 11575 11578 (fontified t) 11578 11583 (face font-lock-keyword-face fontified t) 11583 11584 (fontified t) 11584 11610 (face font-lock-type-face fontified t) 11610 11611 (face (rainbow-delimiters-depth-1-face) fontified t) 11611 11629 (fontified t) 11629 11630 (face (rainbow-delimiters-depth-1-face) fontified t) 11630 11631 (prettify-symbols-end 11763 prettify-symbols-start 11762 composition (0 1 [32 65 57708]) fontified t) 11631 11636 (fontified t) 11636 11638 (face font-lock-doc-face fontified t) 11638 11639 (face font-lock-doc-face syntax-table (15) fontified t) 11639 11677 (face font-lock-doc-face fontified t) 11677 11678 (face font-lock-doc-face syntax-table (15) fontified t) 11678 11680 (face font-lock-doc-face fontified t) 11680 11699 (fontified t) 11699 11700 (prettify-symbols-end 11832 prettify-symbols-start 11831 composition (0 1 [32 65 57708]) fontified t) 11700 11719 (fontified t) 11719 11721 (face font-lock-string-face fontified t) 11721 11722 (face font-lock-string-face syntax-table (15) fontified t) 11722 11867 (face font-lock-string-face fontified t) 11867 11868 (face font-lock-string-face syntax-table (15) fontified t) 11868 11870 (face font-lock-string-face fontified t) 11870 11883 (fontified t) 11883 11884 (prettify-symbols-end 12016 prettify-symbols-start 12015 composition (0 1 [32 65 57708]) fontified t) 11884 11885 (fontified t) 11885 11890 (face font-lock-builtin-face fontified t) 11890 11895 (fontified t) 11895 11897 (face font-lock-string-face fontified t) 11897 11898 (face font-lock-string-face syntax-table (15) fontified t) 11898 12014 (face font-lock-string-face fontified t) 12014 12015 (face font-lock-string-face syntax-table (15) fontified t) 12015 12017 (face font-lock-string-face fontified t) 12017 12027 (fontified t) 12027 12028 (prettify-symbols-end 12160 prettify-symbols-start 12159 composition (0 1 [32 65 57708]) fontified t) 12028 12029 (fontified t) 12029 12034 (face font-lock-builtin-face fontified t) 12034 12035 (fontified t) 12035 12036 (face font-lock-operator-face fontified t) 12036 12037 (fontified t) 12037 12041 (face font-lock-constant-face fontified t) 12041 12042 (fontified t) 12042 12043 (face font-lock-operator-face fontified t) 12043 12044 (fontified t) 12044 12048 (face font-lock-constant-face fontified t) 12048 12053 (fontified t) 12053 12055 (face font-lock-doc-face fontified t) 12055 12056 (face font-lock-doc-face syntax-table (15) fontified t) 12056 12128 (face font-lock-doc-face fontified t) 12128 12129 (face font-lock-doc-face syntax-table (15) fontified t) 12129 12131 (face font-lock-doc-face fontified t) 12131 12143 (fontified t) 12143 12144 (prettify-symbols-end 12276 prettify-symbols-start 12275 composition (0 1 [32 65 57708]) fontified t) 12144 12145 (fontified t) 12145 12148 (face font-lock-builtin-face fontified t) 12148 12149 (fontified t) 12149 12150 (face font-lock-operator-face fontified t) 12150 12151 (fontified t) 12151 12155 (face font-lock-constant-face fontified t) 12155 12156 (fontified t) 12156 12157 (face font-lock-operator-face fontified t) 12157 12158 (fontified t) 12158 12162 (face font-lock-constant-face fontified t) 12162 12167 (fontified t) 12167 12169 (face font-lock-doc-face fontified t) 12169 12170 (face font-lock-doc-face syntax-table (15) fontified t) 12170 12278 (face font-lock-doc-face fontified t) 12278 12279 (face font-lock-doc-face syntax-table (15) fontified t) 12279 12281 (face font-lock-doc-face fontified t) 12281 12286 (fontified t) 12286 12298 (face font-lock-variable-name-face fontified t) 12298 12299 (fontified t) 12299 12300 (face font-lock-operator-face fontified t) 12300 12311 (fontified t) 12311 12312 (face (rainbow-delimiters-depth-1-face) fontified t) 12312 12317 (fontified t) 12317 12318 (face font-lock-operator-face fontified t) 12318 12325 (face font-lock-string-face fontified t) 12325 12326 (face (rainbow-delimiters-depth-1-face) fontified t) 12326 12329 (fontified t) 12329 12334 (face font-lock-keyword-face fontified t) 12334 12335 (fontified t) 12335 12355 (face font-lock-type-face fontified t) 12355 12356 (face (rainbow-delimiters-depth-1-face) fontified t) 12356 12368 (fontified t) 12368 12369 (face (rainbow-delimiters-depth-2-face) fontified t) 12369 12404 (fontified t) 12404 12405 (face (rainbow-delimiters-depth-3-face) fontified t) 12405 12429 (face font-lock-string-face fontified t) 12429 12430 (face (rainbow-delimiters-depth-3-face) fontified t) 12430 12431 (face (rainbow-delimiters-depth-2-face) fontified t) 12431 12432 (face (rainbow-delimiters-depth-1-face) fontified t) 12432 12433 (prettify-symbols-end 12565 prettify-symbols-start 12564 composition (0 1 [32 65 57708]) fontified t) 12433 12438 (fontified t) 12438 12440 (face font-lock-doc-face fontified t) 12440 12441 (face font-lock-doc-face syntax-table (15) fontified t) 12441 12559 (face font-lock-doc-face fontified t) 12559 12560 (face font-lock-doc-face syntax-table (15) fontified t) 12560 12562 (face font-lock-doc-face fontified t) 12562 12574 (fontified t) 12574 12575 (prettify-symbols-end 12707 prettify-symbols-start 12706 composition (0 1 [32 65 57708]) fontified t) 12575 12583 (fontified t) 12583 12584 (face (rainbow-delimiters-depth-1-face) fontified t) 12584 12608 (face font-lock-string-face fontified t) 12608 12609 (face (rainbow-delimiters-depth-1-face) fontified t) 12609 12620 (fontified t) 12620 12621 (prettify-symbols-end 12753 prettify-symbols-start 12752 composition (0 1 [32 65 57708]) fontified t) 12621 12651 (fontified t) 12651 12656 (face font-lock-keyword-face fontified t) 12656 12657 (fontified t) 12657 12677 (face font-lock-type-face fontified t) 12677 12678 (face (rainbow-delimiters-depth-1-face) fontified t) 12678 12689 (fontified t) 12689 12690 (face (rainbow-delimiters-depth-2-face) fontified t) 12690 12697 (fontified t) 12697 12698 (face (rainbow-delimiters-depth-3-face) fontified t) 12698 12714 (face font-lock-string-face fontified t) 12714 12715 (face (rainbow-delimiters-depth-3-face) fontified t) 12715 12716 (face (rainbow-delimiters-depth-2-face) fontified t) 12716 12717 (face (rainbow-delimiters-depth-1-face) fontified t) 12717 12718 (prettify-symbols-end 12850 prettify-symbols-start 12849 composition (0 1 [32 65 57708]) fontified t) 12718 12723 (fontified t) 12723 12725 (face font-lock-doc-face fontified t) 12725 12726 (face font-lock-doc-face syntax-table (15) fontified t) 12726 12793 (face font-lock-doc-face fontified t) 12793 12794 (face font-lock-doc-face syntax-table (15) fontified t) 12794 12796 (face font-lock-doc-face fontified t) 12796 12808 (fontified t) 12808 12809 (prettify-symbols-end 12941 prettify-symbols-start 12940 composition (0 1 [32 65 57708]) fontified t) 12809 12817 (fontified t) 12817 12818 (face (rainbow-delimiters-depth-1-face) fontified t) 12818 12834 (face font-lock-string-face fontified t) 12834 12835 (face (rainbow-delimiters-depth-1-face) fontified t) 12835 12838 (fontified t) 12838 12843 (face font-lock-keyword-face fontified t) 12843 12844 (fontified t) 12844 12855 (face font-lock-type-face fontified t) 12855 12856 (face (rainbow-delimiters-depth-1-face) fontified t) 12856 12865 (fontified t) 12865 12866 (face (rainbow-delimiters-depth-1-face) fontified t) 12866 12867 (prettify-symbols-end 12999 prettify-symbols-start 12998 composition (0 1 [32 65 57708]) fontified t) 12867 12880 (fontified t) 12880 12881 (prettify-symbols-end 13013 prettify-symbols-start 13012 composition (0 1 [32 65 57708]) fontified t) 12881 12882 (fontified t) 12882 12886 (face font-lock-builtin-face fontified t) 12886 12887 (face (rainbow-delimiters-depth-1-face) fontified t) 12887 12891 (fontified t) 12891 12892 (face (rainbow-delimiters-depth-1-face) fontified t) 12892 12893 (fontified t) 12893 12894 (face font-lock-operator-face fontified t) 12894 12895 (fontified t) 12895 12899 (face font-lock-constant-face fontified t) 12899 12900 (fontified t) 12900 12901 (face font-lock-operator-face fontified t) 12901 12902 (fontified t) 12902 12906 (face font-lock-constant-face fontified t) 12906 12919 (fontified t) 12919 12920 (prettify-symbols-end 13052 prettify-symbols-start 13051 composition (0 1 [32 65 57708]) fontified t) 12920 12930 (fontified t) 12930 12931 (face (rainbow-delimiters-depth-1-face) fontified t) 12931 12936 (face font-lock-builtin-face fontified t) 12936 12943 (fontified t) 12943 12944 (face (rainbow-delimiters-depth-2-face) fontified t) 12944 12946 (fontified t) 12946 12947 (face font-lock-operator-face fontified t) 12947 12954 (fontified t) 12954 12955 (face font-lock-operator-face fontified t) 12955 12958 (fontified t) 12958 12959 (face (rainbow-delimiters-depth-2-face) fontified t) 12959 12960 (face (rainbow-delimiters-depth-1-face) fontified t) 12960 12961 (fontified t) 12961 12962 (face font-lock-operator-face fontified t) 12962 12963 (fontified t) 12963 12967 (face font-lock-constant-face fontified t) 12967 12968 (fontified t) 12968 12969 (face font-lock-operator-face fontified t) 12969 12970 (fontified t) 12970 12974 (face font-lock-constant-face fontified t) 12974 12979 (fontified t) 12979 12991 (face font-lock-variable-name-face fontified t) 12991 12992 (fontified t) 12992 12993 (face font-lock-operator-face fontified t) 12993 13004 (fontified t) 13004 13005 (face (rainbow-delimiters-depth-1-face) fontified t) 13005 13010 (fontified t) 13010 13011 (face font-lock-operator-face fontified t) 13011 13018 (face font-lock-string-face fontified t) 13018 13019 (face (rainbow-delimiters-depth-1-face) fontified t) 13019 13022 (fontified t) 13022 13027 (face font-lock-keyword-face fontified t) 13027 13028 (fontified t) 13028 13036 (face font-lock-type-face fontified t) 13036 13037 (face (rainbow-delimiters-depth-1-face) fontified t) 13037 13049 (fontified t) 13049 13050 (face (rainbow-delimiters-depth-1-face) fontified t) 13050 13051 (prettify-symbols-end 13183 prettify-symbols-start 13182 composition (0 1 [32 65 57708]) fontified t) 13051 13056 (fontified t) 13056 13058 (face font-lock-doc-face fontified t) 13058 13059 (face font-lock-doc-face syntax-table (15) fontified t) 13059 13114 (face font-lock-doc-face fontified t) 13114 13115 (face font-lock-doc-face syntax-table (15) fontified t) 13115 13117 (face font-lock-doc-face fontified t) 13117 13126 (fontified t) 13126 13127 (prettify-symbols-end 13259 prettify-symbols-start 13258 composition (0 1 [32 65 57708]) fontified t) 13127 13137 (fontified t) 13137 13138 (face (rainbow-delimiters-depth-1-face) fontified t) 13138 13160 (fontified t) 13160 13161 (face (rainbow-delimiters-depth-2-face) fontified t) 13161 13174 (fontified t) 13174 13175 (face font-lock-operator-face fontified t) 13175 13180 (face font-lock-constant-face fontified t) 13180 13181 (face (rainbow-delimiters-depth-2-face) fontified t) 13181 13182 (face (rainbow-delimiters-depth-1-face) fontified t) 13182 13187 (fontified t) 13187 13189 (face font-lock-string-face fontified t) 13189 13190 (face font-lock-string-face syntax-table (15) fontified t) 13190 13215 (face font-lock-string-face fontified t) 13215 13216 (face font-lock-string-face syntax-table (15) fontified t) 13216 13218 (face font-lock-string-face fontified t) 13218 13234 (fontified t) 13234 13235 (prettify-symbols-end 13367 prettify-symbols-start 13366 composition (0 1 [32 65 57708]) fontified t) 13235 13236 (fontified t) 13236 13239 (face font-lock-builtin-face fontified t) 13239 13240 (fontified t) 13240 13241 (face font-lock-operator-face fontified t) 13241 13242 (fontified t) 13242 13246 (face font-lock-constant-face fontified t) 13246 13247 (fontified t) 13247 13248 (face font-lock-operator-face fontified t) 13248 13249 (fontified t) 13249 13253 (face font-lock-constant-face fontified t) 13253 13258 (fontified t) 13258 13260 (face font-lock-doc-face fontified t) 13260 13261 (face font-lock-doc-face syntax-table (15) fontified t) 13261 13308 (face font-lock-doc-face fontified t) 13308 13309 (face font-lock-doc-face syntax-table (15) fontified t) 13309 13311 (face font-lock-doc-face fontified t) 13311 13324 (fontified t) 13324 13325 (prettify-symbols-end 13457 prettify-symbols-start 13456 composition (0 1 [32 65 57708]) fontified t) 13325 13326 (fontified t) 13326 13329 (face font-lock-builtin-face fontified t) 13329 13330 (fontified t) 13330 13331 (face font-lock-operator-face fontified t) 13331 13332 (fontified t) 13332 13336 (face font-lock-constant-face fontified t) 13336 13337 (fontified t) 13337 13338 (face font-lock-operator-face fontified t) 13338 13339 (fontified t) 13339 13343 (face font-lock-constant-face fontified t) 13343 13348 (fontified t) 13348 13350 (face font-lock-doc-face fontified t) 13350 13351 (face font-lock-doc-face syntax-table (15) fontified t) 13351 13392 (face font-lock-doc-face fontified t) 13392 13393 (face font-lock-doc-face syntax-table (15) fontified t) 13393 13395 (face font-lock-doc-face fontified t) 13395 13404 (fontified t) 13404 13405 (prettify-symbols-end 13537 prettify-symbols-start 13536 composition (0 1 [32 65 57708]) fontified t) 13405 13406 (fontified t) 13406 13409 (face font-lock-builtin-face fontified t) 13409 13410 (fontified t) 13410 13411 (face font-lock-operator-face fontified t) 13411 13412 (fontified t) 13412 13416 (face font-lock-constant-face fontified t) 13416 13417 (fontified t) 13417 13418 (face font-lock-operator-face fontified t) 13418 13419 (fontified t) 13419 13423 (face font-lock-constant-face fontified t) 13423 13428 (fontified t) 13428 13430 (face font-lock-doc-face fontified t) 13430 13431 (face font-lock-doc-face syntax-table (15) fontified t) 13431 13641 (face font-lock-doc-face fontified t) 13641 13642 (face font-lock-doc-face syntax-table (15) fontified t) 13642 13644 (face font-lock-doc-face fontified t) 13644 13660 (fontified t) 13660 13661 (prettify-symbols-end 13793 prettify-symbols-start 13792 composition (0 1 [32 65 57708]) fontified t) 13661 13674 (fontified t) 13674 13675 (face font-lock-operator-face fontified t) 13675 13676 (fontified t) 13676 13680 (face font-lock-constant-face fontified t) 13680 13681 (fontified t) 13681 13682 (face font-lock-operator-face fontified t) 13682 13683 (fontified t) 13683 13687 (face font-lock-constant-face fontified t) 13687 13696 (fontified t) 13696 13697 (prettify-symbols-end 13829 prettify-symbols-start 13828 composition (0 1 [32 65 57708]) fontified t) 13697 13698 (fontified t) 13698 13702 (face font-lock-builtin-face fontified t) 13702 13703 (face (rainbow-delimiters-depth-1-face) fontified t) 13703 13706 (face font-lock-builtin-face fontified t) 13706 13711 (fontified t) 13711 13712 (face (rainbow-delimiters-depth-1-face) fontified t) 13712 13713 (fontified t) 13713 13714 (face font-lock-operator-face fontified t) 13714 13715 (fontified t) 13715 13719 (face font-lock-constant-face fontified t) 13719 13720 (fontified t) 13720 13721 (face font-lock-operator-face fontified t) 13721 13727 (fontified t) 13727 13728 (face (rainbow-delimiters-depth-1-face) fontified t) 13728 13733 (fontified t) 13733 13734 (face font-lock-operator-face fontified t) 13734 13741 (face font-lock-string-face fontified t) 13741 13750 (fontified t) 13750 13751 (face font-lock-operator-face fontified t) 13751 13755 (face font-lock-constant-face fontified t) 13755 13756 (face (rainbow-delimiters-depth-1-face) fontified t) 13756 13761 (fontified t) 13761 13763 (face font-lock-doc-face fontified t) 13763 13764 (face font-lock-doc-face syntax-table (15) fontified t) 13764 13991 (face font-lock-doc-face fontified t) 13991 13992 (face font-lock-doc-face syntax-table (15) fontified t) 13992 13994 (face font-lock-doc-face fontified t) 13994 13999 (fontified t) 13999 14011 (face font-lock-variable-name-face fontified t) 14011 14012 (fontified t) 14012 14013 (face font-lock-operator-face fontified t) 14013 14024 (fontified t) 14024 14025 (face (rainbow-delimiters-depth-1-face) fontified t) 14025 14030 (fontified t) 14030 14031 (face font-lock-operator-face fontified t) 14031 14038 (face font-lock-string-face fontified t) 14038 14039 (face (rainbow-delimiters-depth-1-face) fontified t) 14039 14045 (fontified t) 14045 14061 (face font-lock-type-face fontified t) 14061 14062 (face (rainbow-delimiters-depth-1-face) fontified t) 14062 14066 (fontified t) 14066 14067 (face font-lock-operator-face fontified t) 14067 14074 (face font-lock-string-face fontified t) 14074 14075 (face (rainbow-delimiters-depth-1-face) fontified t) 14075 14080 (fontified t) 14080 14083 (face font-lock-keyword-face fontified t) 14083 14084 (fontified t) 14084 14103 (face font-lock-function-name-face fontified t) 14103 14104 (face (rainbow-delimiters-depth-1-face) fontified t) 14104 14108 (face font-lock-keyword-face fontified t) 14108 14109 (face (rainbow-delimiters-depth-1-face) fontified t) 14109 14110 (fontified t) 14110 14111 (face font-lock-operator-face prettify-symbols-end 14244 prettify-symbols-start 14242 composition ((2 32 63 32 65 57620)) fontified t) 14111 14112 (face font-lock-operator-face prettify-symbols-end 14244 prettify-symbols-start 14242 composition ((2 32 63 32 65 57620)) fontified t) 14112 14113 (fontified t) 14113 14123 (face font-lock-string-face fontified t) 14123 14124 (prettify-symbols-end 14256 prettify-symbols-start 14255 composition ((1 32 65 57708)) fontified t) 14124 14133 (fontified t) 14133 14135 (face font-lock-doc-face fontified t) 14135 14136 (face font-lock-doc-face syntax-table (15) fontified t) 14136 14185 (face font-lock-doc-face fontified t) 14185 14186 (face font-lock-doc-face syntax-table (15) fontified t) 14186 14188 (face font-lock-doc-face fontified t) 14188 14197 (fontified t) 14197 14204 (face font-lock-variable-name-face fontified t) 14204 14205 (fontified t) 14205 14206 (face font-lock-operator-face fontified t) 14206 14207 (fontified t) 14207 14210 (face font-lock-builtin-face fontified t) 14210 14211 (face (rainbow-delimiters-depth-1-face) fontified t) 14211 14215 (face font-lock-keyword-face fontified t) 14215 14219 (fontified t) 14219 14220 (face (rainbow-delimiters-depth-1-face) fontified t) 14220 14229 (fontified t) 14229 14231 (face font-lock-keyword-face fontified t) 14231 14250 (fontified t) 14250 14251 (face (rainbow-delimiters-depth-1-face) fontified t) 14251 14252 (face (rainbow-delimiters-depth-2-face) fontified t) 14252 14261 (face font-lock-string-face fontified t) 14261 14263 (fontified t) 14263 14274 (face font-lock-string-face fontified t) 14274 14275 (face (rainbow-delimiters-depth-2-face) fontified t) 14275 14276 (face (rainbow-delimiters-depth-1-face) fontified t) 14276 14277 (prettify-symbols-end 14409 prettify-symbols-start 14408 composition ((1 32 65 57708)) fontified t) 14277 14290 (fontified t) 14290 14295 (face font-lock-keyword-face fontified t) 14295 14296 (fontified t) 14296 14306 (face font-lock-type-face fontified t) 14306 14307 (face (rainbow-delimiters-depth-1-face) fontified t) 14307 14308 (fontified t) 14308 14381 (face font-lock-string-face fontified t) 14381 14382 (face nil fontified t) 14382 14386 (face font-lock-keyword-face fontified t) 14386 14391 (face nil fontified t) 14391 14392 (face font-lock-string-face fontified t) 14392 14393 (face (rainbow-delimiters-depth-1-face) fontified t) 14393 14402 (fontified t) 14402 14408 (face font-lock-keyword-face fontified t) 14408 14409 (fontified t) 14409 14413 (face font-lock-keyword-face fontified t) 14413 14416 (fontified t) 14416 14421 (face font-lock-keyword-face fontified t) 14421 14422 (fontified t) 14422 14438 (face font-lock-type-face fontified t) 14438 14439 (face (rainbow-delimiters-depth-1-face) fontified t) 14439 14451 (fontified t) 14451 14452 (face (rainbow-delimiters-depth-1-face) fontified t) 14452 14453 (prettify-symbols-end 14585 prettify-symbols-start 14584 composition (0 1 [32 65 57708]) fontified t) 14453 14458 (fontified t) 14458 14460 (face font-lock-doc-face fontified t) 14460 14461 (face font-lock-doc-face syntax-table (15) fontified t) 14461 14522 (face font-lock-doc-face fontified t) 14522 14523 (face font-lock-doc-face syntax-table (15) fontified t) 14523 14525 (face font-lock-doc-face fontified t) 14525 14542 (fontified t) 14542 14543 (prettify-symbols-end 14675 prettify-symbols-start 14674 composition (0 1 [32 65 57708]) fontified t) 14543 14544 (fontified t) 14544 14547 (face font-lock-builtin-face fontified t) 14547 14552 (fontified t) 14552 14554 (face font-lock-string-face fontified t) 14554 14555 (face font-lock-string-face syntax-table (15) fontified t) 14555 14652 (face font-lock-string-face fontified t) 14652 14653 (face font-lock-string-face syntax-table (15) fontified t) 14653 14655 (face font-lock-string-face fontified t) 14655 14671 (fontified t) 14671 14672 (prettify-symbols-end 14804 prettify-symbols-start 14803 composition (0 1 [32 65 57708]) fontified t) 14672 14673 (fontified t) 14673 14676 (face font-lock-builtin-face fontified t) 14676 14677 (fontified t) 14677 14678 (face font-lock-operator-face fontified t) 14678 14679 (fontified t) 14679 14683 (face font-lock-constant-face fontified t) 14683 14684 (fontified t) 14684 14685 (face font-lock-operator-face fontified t) 14685 14686 (fontified t) 14686 14690 (face font-lock-constant-face fontified t) 14690 14695 (fontified t) 14695 14697 (face font-lock-doc-face fontified t) 14697 14698 (face font-lock-doc-face syntax-table (15) fontified t) 14698 14756 (face font-lock-doc-face fontified t) 14756 14757 (face font-lock-doc-face syntax-table (15) fontified t) 14757 14759 (face font-lock-doc-face fontified t) 14759 14772 (fontified t) 14772 14773 (prettify-symbols-end 14905 prettify-symbols-start 14904 composition (0 1 [32 65 57708]) fontified t) 14773 14774 (fontified t) 14774 14777 (face font-lock-builtin-face fontified t) 14777 14778 (fontified t) 14778 14779 (face font-lock-operator-face fontified t) 14779 14780 (fontified t) 14780 14784 (face font-lock-constant-face fontified t) 14784 14785 (fontified t) 14785 14786 (face font-lock-operator-face fontified t) 14786 14787 (fontified t) 14787 14791 (face font-lock-constant-face fontified t) 14791 14796 (fontified t) 14796 14798 (face font-lock-doc-face fontified t) 14798 14799 (face font-lock-doc-face syntax-table (15) fontified t) 14799 14959 (face font-lock-doc-face fontified t) 14959 14960 (face font-lock-doc-face syntax-table (15) fontified t) 14960 14962 (face font-lock-doc-face fontified t) 14962 14978 (fontified t) 14978 14979 (prettify-symbols-end 15111 prettify-symbols-start 15110 composition (0 1 [32 65 57708]) fontified t) 14979 14992 (fontified t) 14992 14993 (face font-lock-operator-face fontified t) 14993 14994 (fontified t) 14994 14998 (face font-lock-constant-face fontified t) 14998 14999 (fontified t) 14999 15000 (face font-lock-operator-face fontified t) 15000 15001 (fontified t) 15001 15005 (face font-lock-constant-face fontified t) 15005 15014 (fontified t) 15014 15015 (prettify-symbols-end 15147 prettify-symbols-start 15146 composition (0 1 [32 65 57708]) fontified t) 15015 15016 (fontified t) 15016 15020 (face font-lock-builtin-face fontified t) 15020 15021 (face (rainbow-delimiters-depth-1-face) fontified t) 15021 15024 (face font-lock-builtin-face fontified t) 15024 15029 (fontified t) 15029 15030 (face (rainbow-delimiters-depth-1-face) fontified t) 15030 15031 (fontified t) 15031 15032 (face font-lock-operator-face fontified t) 15032 15033 (fontified t) 15033 15037 (face font-lock-constant-face fontified t) 15037 15038 (fontified t) 15038 15039 (face font-lock-operator-face fontified t) 15039 15045 (fontified t) 15045 15046 (face (rainbow-delimiters-depth-1-face) fontified t) 15046 15051 (fontified t) 15051 15052 (face font-lock-operator-face fontified t) 15052 15059 (face font-lock-string-face fontified t) 15059 15068 (fontified t) 15068 15069 (face font-lock-operator-face fontified t) 15069 15073 (face font-lock-constant-face fontified t) 15073 15074 (face (rainbow-delimiters-depth-1-face) fontified t) 15074 15079 (fontified t) 15079 15081 (face font-lock-doc-face fontified t) 15081 15082 (face font-lock-doc-face syntax-table (15) fontified t) 15082 15309 (face font-lock-doc-face fontified t) 15309 15310 (face font-lock-doc-face syntax-table (15) fontified t) 15310 15312 (face font-lock-doc-face fontified t) 15312 15317 (fontified t) 15317 15329 (face font-lock-variable-name-face fontified t) 15329 15330 (fontified t) 15330 15331 (face font-lock-operator-face fontified t) 15331 15342 (fontified t) 15342 15343 (face (rainbow-delimiters-depth-1-face) fontified t) 15343 15348 (fontified t) 15348 15349 (face font-lock-operator-face fontified t) 15349 15356 (face font-lock-string-face fontified t) 15356 15357 (face (rainbow-delimiters-depth-1-face) fontified t) 15357 15360 (fontified t) 15360 15365 (face font-lock-keyword-face fontified t) 15365 15366 (fontified t) 15366 15385 (face font-lock-type-face fontified t) 15385 15386 (face (rainbow-delimiters-depth-1-face) fontified t) 15386 15396 (fontified t) 15396 15397 (face (rainbow-delimiters-depth-1-face) fontified t) 15397 15398 (prettify-symbols-end 15530 prettify-symbols-start 15529 composition (0 1 [32 65 57708]) fontified t) 15398 15403 (fontified t) 15403 15405 (face font-lock-doc-face fontified t) 15405 15406 (face font-lock-doc-face syntax-table (15) fontified t) 15406 15472 (face font-lock-doc-face fontified t) 15472 15473 (face font-lock-doc-face syntax-table (15) fontified t) 15473 15475 (face font-lock-doc-face fontified t) 15475 15490 (fontified t) 15490 15491 (prettify-symbols-end 15623 prettify-symbols-start 15622 composition (0 1 [32 65 57708]) fontified t) 15491 15492 (fontified t) 15492 15496 (face font-lock-builtin-face fontified t) 15496 15497 (face (rainbow-delimiters-depth-1-face) fontified t) 15497 15505 (fontified t) 15505 15506 (face (rainbow-delimiters-depth-1-face) fontified t) 15506 15509 (fontified t) 15509 15514 (face font-lock-keyword-face fontified t) 15514 15515 (fontified t) 15515 15543 (face font-lock-type-face fontified t) 15543 15544 (face (rainbow-delimiters-depth-1-face) fontified t) 15544 15555 (fontified t) 15555 15556 (face (rainbow-delimiters-depth-2-face) fontified t) 15556 15563 (fontified t) 15563 15564 (face (rainbow-delimiters-depth-3-face) fontified t) 15564 15590 (face font-lock-string-face fontified t) 15590 15591 (face (rainbow-delimiters-depth-3-face) fontified t) 15591 15592 (face (rainbow-delimiters-depth-2-face) fontified t) 15592 15593 (face (rainbow-delimiters-depth-1-face) fontified t) 15593 15594 (prettify-symbols-end 15726 prettify-symbols-start 15725 composition (0 1 [32 65 57708]) fontified t) 15594 15599 (fontified t) 15599 15601 (face font-lock-doc-face fontified t) 15601 15602 (face font-lock-doc-face syntax-table (15) fontified t) 15602 15678 (face font-lock-doc-face fontified t) 15678 15679 (face font-lock-doc-face syntax-table (15) fontified t) 15679 15681 (face font-lock-doc-face fontified t) 15681 15693 (fontified t) 15693 15694 (prettify-symbols-end 15826 prettify-symbols-start 15825 composition (0 1 [32 65 57708]) fontified t) 15694 15702 (fontified t) 15702 15703 (face (rainbow-delimiters-depth-1-face) fontified t) 15703 15729 (face font-lock-string-face fontified t) 15729 15730 (face (rainbow-delimiters-depth-1-face) fontified t) 15730 15733 (fontified t) 15733 15738 (face font-lock-keyword-face fontified t) 15738 15739 (fontified t) 15739 15766 (face font-lock-type-face fontified t) 15766 15767 (face (rainbow-delimiters-depth-1-face) fontified t) 15767 15777 (fontified t) 15777 15778 (face (rainbow-delimiters-depth-1-face) fontified t) 15778 15779 (prettify-symbols-end 15911 prettify-symbols-start 15910 composition (0 1 [32 65 57708]) fontified t) 15779 15784 (fontified t) 15784 15786 (face font-lock-doc-face fontified t) 15786 15787 (face font-lock-doc-face syntax-table (15) fontified t) 15787 15863 (face font-lock-doc-face fontified t) 15863 15864 (face font-lock-doc-face syntax-table (15) fontified t) 15864 15866 (face font-lock-doc-face fontified t) 15866 15889 (fontified t) 15889 15890 (prettify-symbols-end 16022 prettify-symbols-start 16021 composition (0 1 [32 65 57708]) fontified t) 15890 15891 (fontified t) 15891 15895 (face font-lock-builtin-face fontified t) 15895 15896 (face (rainbow-delimiters-depth-1-face) fontified t) 15896 15912 (fontified t) 15912 15913 (face (rainbow-delimiters-depth-1-face) fontified t) 15913 15916 (fontified t) 15916 15921 (face font-lock-keyword-face fontified t) 15921 15922 (fontified t) 15922 15947 (face font-lock-type-face fontified t) 15947 15948 (face (rainbow-delimiters-depth-1-face) fontified t) 15948 15961 (fontified t) 15961 15962 (face (rainbow-delimiters-depth-1-face) fontified t) 15962 15963 (prettify-symbols-end 16095 prettify-symbols-start 16094 composition (0 1 [32 65 57708]) fontified t) 15963 15968 (fontified t) 15968 15970 (face font-lock-doc-face fontified t) 15970 15971 (face font-lock-doc-face syntax-table (15) fontified t) 15971 16005 (face font-lock-doc-face fontified t) 16005 16006 (face font-lock-doc-face syntax-table (15) fontified t) 16006 16008 (face font-lock-doc-face fontified t) 16008 16017 (fontified t) 16017 16018 (prettify-symbols-end 16150 prettify-symbols-start 16149 composition (0 1 [32 65 57708]) fontified t) 16018 16028 (fontified t) 16028 16029 (face (rainbow-delimiters-depth-1-face) fontified t) 16029 16051 (fontified t) 16051 16052 (face (rainbow-delimiters-depth-2-face) fontified t) 16052 16065 (fontified t) 16065 16066 (face font-lock-operator-face fontified t) 16066 16071 (face font-lock-constant-face fontified t) 16071 16072 (face (rainbow-delimiters-depth-2-face) fontified t) 16072 16073 (face (rainbow-delimiters-depth-1-face) fontified t) 16073 16078 (fontified t) 16078 16080 (face font-lock-string-face fontified t) 16080 16081 (face font-lock-string-face syntax-table (15) fontified t) 16081 16201 (face font-lock-string-face fontified t) 16201 16202 (face font-lock-string-face syntax-table (15) fontified t) 16202 16204 (face font-lock-string-face fontified t) 16204 16209 (fontified t) 16209 16221 (face font-lock-variable-name-face fontified t) 16221 16222 (fontified t) 16222 16223 (face font-lock-operator-face fontified t) 16223 16234 (fontified t) 16234 16235 (face (rainbow-delimiters-depth-1-face) fontified t) 16235 16240 (fontified t) 16240 16241 (face font-lock-operator-face fontified t) 16241 16248 (face font-lock-string-face fontified t) 16248 16249 (face (rainbow-delimiters-depth-1-face) fontified t) 16249 16252 (fontified t) 16252 16257 (face font-lock-keyword-face fontified t) 16257 16258 (fontified t) 16258 16277 (face font-lock-type-face fontified t) 16277 16278 (face (rainbow-delimiters-depth-1-face) fontified t) 16278 16285 (fontified t) 16285 16286 (face (rainbow-delimiters-depth-2-face) fontified t) 16286 16320 (fontified t) 16320 16321 (face (rainbow-delimiters-depth-3-face) fontified t) 16321 16337 (face font-lock-string-face fontified t) 16337 16338 (face (rainbow-delimiters-depth-3-face) fontified t) 16338 16339 (face (rainbow-delimiters-depth-2-face) fontified t) 16339 16340 (face (rainbow-delimiters-depth-1-face) fontified t) 16340 16341 (prettify-symbols-end 16473 prettify-symbols-start 16472 composition (0 1 [32 65 57708]) fontified t) 16341 16346 (fontified t) 16346 16348 (face font-lock-doc-face fontified t) 16348 16349 (face font-lock-doc-face syntax-table (15) fontified t) 16349 16417 (face font-lock-doc-face fontified t) 16417 16418 (face font-lock-doc-face syntax-table (15) fontified t) 16418 16420 (face font-lock-doc-face fontified t) 16420 16432 (fontified t) 16432 16433 (prettify-symbols-end 16565 prettify-symbols-start 16564 composition (0 1 [32 65 57708]) fontified t) 16433 16441 (fontified t) 16441 16442 (face (rainbow-delimiters-depth-1-face) fontified t) 16442 16458 (face font-lock-string-face fontified t) 16458 16459 (face (rainbow-delimiters-depth-1-face) fontified t) 16459 16470 (fontified t) 16470 16471 (prettify-symbols-end 16603 prettify-symbols-start 16602 composition (0 1 [32 65 57708]) fontified t) 16471 16500 (fontified t) 16500 16505 (face font-lock-keyword-face fontified t) 16505 16506 (fontified t) 16506 16522 (face font-lock-type-face fontified t) 16522 16523 (face (rainbow-delimiters-depth-1-face) fontified t) 16523 16532 (fontified t) 16532 16533 (face (rainbow-delimiters-depth-1-face) fontified t) 16533 16534 (prettify-symbols-end 16666 prettify-symbols-start 16665 composition (0 1 [32 65 57708]) fontified t) 16534 16539 (fontified t) 16539 16541 (face font-lock-doc-face fontified t) 16541 16542 (face font-lock-doc-face syntax-table (15) fontified t) 16542 16594 (face font-lock-doc-face fontified t) 16594 16595 (face font-lock-doc-face syntax-table (15) fontified t) 16595 16597 (face font-lock-doc-face fontified t) 16597 16606 (fontified t) 16606 16607 (prettify-symbols-end 16739 prettify-symbols-start 16738 composition ((1 32 65 57708)) fontified t) 16607 16617 (fontified t) 16617 16618 (face (rainbow-delimiters-depth-1-face) fontified t) 16618 16640 (fontified t) 16640 16641 (face (rainbow-delimiters-depth-2-face) fontified t) 16641 16654 (fontified t) 16654 16655 (face font-lock-operator-face fontified t) 16655 16660 (face font-lock-constant-face fontified t) 16660 16661 (face (rainbow-delimiters-depth-2-face) fontified t) 16661 16662 (face (rainbow-delimiters-depth-1-face) fontified t) 16662 16667 (fontified t) 16667 16669 (face font-lock-string-face fontified t) 16669 16670 (face font-lock-string-face syntax-table (15) fontified t) 16670 16695 (face font-lock-string-face fontified t) 16695 16696 (face font-lock-string-face syntax-table (15) fontified t) 16696 16698 (face font-lock-string-face fontified t) 16698 16711 (fontified t) 16711 16712 (prettify-symbols-end 16844 prettify-symbols-start 16843 composition ((1 32 65 57708)) fontified t) 16712 16713 (fontified t) 16713 16716 (face font-lock-builtin-face fontified t) 16716 16717 (fontified t) 16717 16718 (face font-lock-operator-face fontified t) 16718 16719 (fontified t) 16719 16723 (face font-lock-constant-face fontified t) 16723 16724 (fontified t) 16724 16725 (face font-lock-operator-face fontified t) 16725 16726 (fontified t) 16726 16730 (face font-lock-constant-face fontified t) 16730 16735 (fontified t) 16735 16737 (face font-lock-doc-face fontified t) 16737 16738 (face font-lock-doc-face syntax-table (15) fontified t) 16738 16779 (face font-lock-doc-face fontified t) 16779 16780 (face font-lock-doc-face syntax-table (15) fontified t) 16780 16782 (face font-lock-doc-face fontified t) 16782 16791 (fontified t) 16791 16792 (prettify-symbols-end 16924 prettify-symbols-start 16923 composition ((1 32 65 57708)) fontified t) 16792 16793 (fontified t) 16793 16797 (face font-lock-builtin-face fontified t) 16797 16798 (face (rainbow-delimiters-depth-1-face) fontified t) 16798 16801 (face font-lock-builtin-face fontified t) 16801 16806 (fontified t) 16806 16807 (face (rainbow-delimiters-depth-1-face) fontified t) 16807 16808 (fontified t) 16808 16809 (face font-lock-operator-face fontified t) 16809 16810 (fontified t) 16810 16814 (face font-lock-constant-face fontified t) 16814 16815 (fontified t) 16815 16816 (face font-lock-operator-face fontified t) 16816 16822 (fontified t) 16822 16823 (face (rainbow-delimiters-depth-1-face) fontified t) 16823 16828 (fontified t) 16828 16829 (face font-lock-operator-face fontified t) 16829 16836 (face font-lock-string-face fontified t) 16836 16845 (fontified t) 16845 16846 (face font-lock-operator-face fontified t) 16846 16850 (face font-lock-constant-face fontified t) 16850 16851 (face (rainbow-delimiters-depth-1-face) fontified t) 16851 16856 (fontified t) 16856 16858 (face font-lock-doc-face fontified t) 16858 16859 (face font-lock-doc-face syntax-table (15) fontified t) 16859 17086 (face font-lock-doc-face fontified t) 17086 17087 (face font-lock-doc-face syntax-table (15) fontified t) 17087 17089 (face font-lock-doc-face fontified t) 17089 17094 (fontified t) 17094 17106 (face font-lock-variable-name-face fontified t) 17106 17107 (fontified t) 17107 17108 (face font-lock-operator-face fontified t) 17108 17119 (fontified t) 17119 17120 (face (rainbow-delimiters-depth-1-face) fontified t) 17120 17125 (fontified t) 17125 17126 (face font-lock-operator-face fontified t) 17126 17133 (face font-lock-string-face fontified t) 17133 17134 (face (rainbow-delimiters-depth-1-face) fontified t) 17134 17137 (fontified t) 17137 17142 (face font-lock-keyword-face fontified t) 17142 17143 (fontified t) 17143 17163 (face font-lock-type-face fontified t) 17163 17164 (face (rainbow-delimiters-depth-1-face) fontified t) 17164 17180 (fontified t) 17180 17181 (face (rainbow-delimiters-depth-1-face) fontified t) 17181 17182 (prettify-symbols-end 17314 prettify-symbols-start 17313 composition ((1 32 65 57708)) fontified t) 17182 17187 (fontified t) 17187 17189 (face font-lock-doc-face fontified t) 17189 17190 (face font-lock-doc-face syntax-table (15) fontified t) 17190 17218 (face font-lock-doc-face fontified t) 17218 17219 (face font-lock-doc-face syntax-table (15) fontified t) 17219 17221 (face font-lock-doc-face fontified t) 17221 17231 (fontified t) 17231 17232 (prettify-symbols-end 17364 prettify-symbols-start 17363 composition ((1 32 65 57708)) fontified t) 17232 17233 (fontified t) 17233 17236 (face font-lock-builtin-face fontified t) 17236 17241 (fontified t) 17241 17243 (face font-lock-string-face fontified t) 17243 17244 (face font-lock-string-face syntax-table (15) fontified t) 17244 17368 (face font-lock-string-face fontified t) 17368 17369 (face font-lock-string-face syntax-table (15) fontified t) 17369 17371 (face font-lock-string-face fontified t) 17371 17374 (fontified t) 17374 17379 (face font-lock-keyword-face fontified t) 17379 17380 (fontified t) 17380 17400 (face font-lock-type-face fontified t) 17400 17401 (face (rainbow-delimiters-depth-1-face) fontified t) 17401 17417 (fontified t) 17417 17418 (face (rainbow-delimiters-depth-1-face) fontified t) 17418 17419 (prettify-symbols-end 17551 prettify-symbols-start 17550 composition (0 1 [32 65 57708]) fontified t) 17419 17424 (fontified t) 17424 17426 (face font-lock-doc-face fontified t) 17426 17427 (face font-lock-doc-face syntax-table (15) fontified t) 17427 17457 (face font-lock-doc-face fontified t) 17457 17458 (face font-lock-doc-face syntax-table (15) fontified t) 17458 17460 (face font-lock-doc-face fontified t) 17460 17470 (fontified t) 17470 17471 (prettify-symbols-end 17603 prettify-symbols-start 17602 composition (0 1 [32 65 57708]) fontified t) 17471 17472 (fontified t) 17472 17475 (face font-lock-builtin-face fontified t) 17475 17480 (fontified t) 17480 17482 (face font-lock-string-face fontified t) 17482 17483 (face font-lock-string-face syntax-table (15) fontified t) 17483 17548 (face font-lock-string-face fontified t) 17548 17549 (face font-lock-string-face syntax-table (15) fontified t) 17549 17551 (face font-lock-string-face fontified t) 17551 17554 (fontified t) 17554 17559 (face font-lock-keyword-face fontified t) 17559 17560 (fontified t) 17560 17578 (face font-lock-type-face fontified t) 17578 17579 (face (rainbow-delimiters-depth-1-face) fontified t) 17579 17585 (fontified t) 17585 17586 (face (rainbow-delimiters-depth-1-face) fontified t) 17586 17587 (prettify-symbols-end 17719 prettify-symbols-start 17718 composition (0 1 [32 65 57708]) fontified t) 17587 17592 (fontified t) 17592 17594 (face font-lock-doc-face fontified t) 17594 17595 (face font-lock-doc-face syntax-table (15) fontified t) 17595 17661 (face font-lock-doc-face fontified t) 17661 17662 (face font-lock-doc-face syntax-table (15) fontified t) 17662 17664 (face font-lock-doc-face fontified t) 17664 17678 (fontified t) 17678 17679 (prettify-symbols-end 17811 prettify-symbols-start 17810 composition (0 1 [32 65 57708]) fontified t) 17679 17680 (fontified t) 17680 17684 (face font-lock-builtin-face fontified t) 17684 17685 (face (rainbow-delimiters-depth-1-face) fontified t) 17685 17706 (fontified t) 17706 17707 (face font-lock-operator-face fontified t) 17707 17728 (fontified t) 17728 17729 (face (rainbow-delimiters-depth-1-face) fontified t) 17729 17732 (fontified t) 17732 17737 (face font-lock-keyword-face fontified t) 17737 17738 (fontified t) 17738 17769 (face font-lock-type-face fontified t) 17769 17770 (face (rainbow-delimiters-depth-1-face) fontified t) 17770 17787 (fontified t) 17787 17788 (face (rainbow-delimiters-depth-2-face) fontified t) 17788 17807 (fontified t) 17807 17808 (face font-lock-operator-face fontified t) 17808 17809 (fontified t) 17809 17813 (face font-lock-constant-face fontified t) 17813 17822 (fontified t) 17822 17823 (face (rainbow-delimiters-depth-3-face) fontified t) 17823 17861 (face font-lock-string-face fontified t) 17861 17862 (face (rainbow-delimiters-depth-3-face) fontified t) 17862 17863 (face (rainbow-delimiters-depth-2-face) fontified t) 17863 17864 (fontified t) 17864 17865 (face (rainbow-delimiters-depth-1-face) fontified t) 17865 17866 (prettify-symbols-end 17998 prettify-symbols-start 17997 composition (0 1 [32 65 57708]) fontified t) 17866 17871 (fontified t) 17871 17873 (face font-lock-doc-face fontified t) 17873 17874 (face font-lock-doc-face syntax-table (15) fontified t) 17874 18013 (face font-lock-doc-face fontified t) 18013 18014 (face font-lock-doc-face syntax-table (15) fontified t) 18014 18016 (face font-lock-doc-face fontified t) 18016 18028 (fontified t) 18028 18029 (prettify-symbols-end 18161 prettify-symbols-start 18160 composition (0 1 [32 65 57708]) fontified t) 18029 18037 (fontified t) 18037 18038 (face (rainbow-delimiters-depth-1-face) fontified t) 18038 18076 (face font-lock-string-face fontified t) 18076 18077 (face (rainbow-delimiters-depth-1-face) fontified t) 18077 18088 (fontified t) 18088 18089 (prettify-symbols-end 18221 prettify-symbols-start 18220 composition (0 1 [32 65 57708]) fontified t) 18089 18109 (fontified t) 18109 18110 (face font-lock-operator-face fontified t) 18110 18111 (fontified t) 18111 18115 (face font-lock-constant-face fontified t) 18115 18116 (fontified t) 18116 18117 (face font-lock-operator-face fontified t) 18117 18118 (fontified t) 18118 18122 (face font-lock-constant-face fontified t) 18122 18125 (fontified t) 18125 18130 (face font-lock-keyword-face fontified t) 18130 18131 (fontified t) 18131 18153 (face font-lock-type-face fontified t) 18153 18154 (face (rainbow-delimiters-depth-1-face) fontified t) 18154 18167 (fontified t) 18167 18168 (face (rainbow-delimiters-depth-1-face) fontified t) 18168 18169 (prettify-symbols-end 18301 prettify-symbols-start 18300 composition (0 1 [32 65 57708]) fontified t) 18169 18174 (fontified t) 18174 18176 (face font-lock-doc-face fontified t) 18176 18177 (face font-lock-doc-face syntax-table (15) fontified t) 18177 18218 (face font-lock-doc-face fontified t) 18218 18219 (face font-lock-doc-face syntax-table (15) fontified t) 18219 18221 (face font-lock-doc-face fontified t) 18221 18230 (fontified t) 18230 18231 (prettify-symbols-end 18363 prettify-symbols-start 18362 composition (0 1 [32 65 57708]) fontified t) 18231 18241 (fontified t) 18241 18242 (face (rainbow-delimiters-depth-1-face) fontified t) 18242 18264 (fontified t) 18264 18265 (face (rainbow-delimiters-depth-2-face) fontified t) 18265 18278 (fontified t) 18278 18279 (face font-lock-operator-face fontified t) 18279 18284 (face font-lock-constant-face fontified t) 18284 18285 (face (rainbow-delimiters-depth-2-face) fontified t) 18285 18286 (face (rainbow-delimiters-depth-1-face) fontified t) 18286 18291 (fontified t) 18291 18293 (face font-lock-string-face fontified t) 18293 18294 (face font-lock-string-face syntax-table (15) fontified t) 18294 18422 (face font-lock-string-face fontified t) 18422 18423 (face font-lock-string-face syntax-table (15) fontified t) 18423 18425 (face font-lock-string-face fontified t) 18425 18430 (fontified t) 18430 18442 (face font-lock-variable-name-face fontified t) 18442 18443 (fontified t) 18443 18444 (face font-lock-operator-face fontified t) 18444 18455 (fontified t) 18455 18456 (face (rainbow-delimiters-depth-1-face) fontified t) 18456 18461 (fontified t) 18461 18462 (face font-lock-operator-face fontified t) 18462 18469 (face font-lock-string-face fontified t) 18469 18470 (face (rainbow-delimiters-depth-1-face) fontified t) 18470 18473 (fontified t) 18473 18478 (face font-lock-keyword-face fontified t) 18478 18479 (fontified t) 18479 18495 (face font-lock-type-face fontified t) 18495 18496 (face (rainbow-delimiters-depth-1-face) fontified t) 18496 18503 (fontified t) 18503 18504 (face (rainbow-delimiters-depth-2-face) fontified t) 18504 18535 (fontified t) 18535 18536 (face (rainbow-delimiters-depth-3-face) fontified t) 18536 18557 (face font-lock-string-face fontified t) 18557 18558 (face (rainbow-delimiters-depth-3-face) fontified t) 18558 18559 (face (rainbow-delimiters-depth-2-face) fontified t) 18559 18560 (face (rainbow-delimiters-depth-1-face) fontified t) 18560 18561 (prettify-symbols-end 18693 prettify-symbols-start 18692 composition (0 1 [32 65 57708]) fontified t) 18561 18566 (fontified t) 18566 18568 (face font-lock-doc-face fontified t) 18568 18569 (face font-lock-doc-face syntax-table (15) fontified t) 18569 18702 (face font-lock-doc-face fontified t) 18702 18703 (face font-lock-doc-face syntax-table (15) fontified t) 18703 18705 (face font-lock-doc-face fontified t) 18705 18717 (fontified t) 18717 18718 (prettify-symbols-end 18850 prettify-symbols-start 18849 composition (0 1 [32 65 57708]) fontified t) 18718 18726 (fontified t) 18726 18727 (face (rainbow-delimiters-depth-1-face) fontified t) 18727 18748 (face font-lock-string-face fontified t) 18748 18749 (face (rainbow-delimiters-depth-1-face) fontified t) 18749 18760 (fontified t) 18760 18761 (prettify-symbols-end 18893 prettify-symbols-start 18892 composition (0 1 [32 65 57708]) fontified t) 18761 18787 (fontified t) 18787 18792 (face font-lock-keyword-face fontified t) 18792 18793 (fontified t) 18793 18817 (face font-lock-type-face fontified t) 18817 18818 (face (rainbow-delimiters-depth-1-face) fontified t) 18818 18831 (fontified t) 18831 18832 (face (rainbow-delimiters-depth-1-face) fontified t) 18832 18833 (prettify-symbols-end 18965 prettify-symbols-start 18964 composition (0 1 [32 65 57708]) fontified t) 18833 18838 (fontified t) 18838 18840 (face font-lock-doc-face fontified t) 18840 18841 (face font-lock-doc-face syntax-table (15) fontified t) 18841 18886 (face font-lock-doc-face fontified t) 18886 18887 (face font-lock-doc-face syntax-table (15) fontified t) 18887 18889 (face font-lock-doc-face fontified t) 18889 18898 (fontified t) 18898 18899 (prettify-symbols-end 19031 prettify-symbols-start 19030 composition (0 1 [32 65 57708]) fontified t) 18899 18909 (fontified t) 18909 18910 (face (rainbow-delimiters-depth-1-face) fontified t) 18910 18932 (fontified t) 18932 18933 (face (rainbow-delimiters-depth-2-face) fontified t) 18933 18946 (fontified t) 18946 18947 (face font-lock-operator-face fontified t) 18947 18952 (face font-lock-constant-face fontified t) 18952 18953 (face (rainbow-delimiters-depth-2-face) fontified t) 18953 18954 (face (rainbow-delimiters-depth-1-face) fontified t) 18954 18959 (fontified t) 18959 18961 (face font-lock-string-face fontified t) 18961 18962 (face font-lock-string-face syntax-table (15) fontified t) 18962 19006 (face font-lock-string-face fontified t) 19006 19007 (face font-lock-string-face syntax-table (15) fontified t) 19007 19009 (face font-lock-string-face fontified t) 19009 19014 (fontified t) 19014 19026 (face font-lock-variable-name-face fontified t) 19026 19027 (fontified t) 19027 19028 (face font-lock-operator-face fontified t) 19028 19039 (fontified t) 19039 19040 (face (rainbow-delimiters-depth-1-face) fontified t) 19040 19045 (fontified t) 19045 19046 (face font-lock-operator-face fontified t) 19046 19053 (face font-lock-string-face fontified t) 19053 19054 (face (rainbow-delimiters-depth-1-face) fontified t) 19054 19057 (fontified t) 19057 19062 (face font-lock-keyword-face fontified t) 19062 19063 (fontified t) 19063 19081 (face font-lock-type-face fontified t) 19081 19082 (face (rainbow-delimiters-depth-1-face) fontified t) 19082 19089 (fontified t) 19089 19090 (face (rainbow-delimiters-depth-2-face) fontified t) 19090 19123 (fontified t) 19123 19124 (face (rainbow-delimiters-depth-3-face) fontified t) 19124 19147 (face font-lock-string-face fontified t) 19147 19148 (face (rainbow-delimiters-depth-3-face) fontified t) 19148 19149 (face (rainbow-delimiters-depth-2-face) fontified t) 19149 19150 (face (rainbow-delimiters-depth-1-face) fontified t) 19150 19151 (prettify-symbols-end 19283 prettify-symbols-start 19282 composition (0 1 [32 65 57708]) fontified t) 19151 19156 (fontified t) 19156 19158 (face font-lock-doc-face fontified t) 19158 19159 (face font-lock-doc-face syntax-table (15) fontified t) 19159 19269 (face font-lock-doc-face fontified t) 19269 19270 (face font-lock-doc-face syntax-table (15) fontified t) 19270 19272 (face font-lock-doc-face fontified t) 19272 19284 (fontified t) 19284 19285 (prettify-symbols-end 19417 prettify-symbols-start 19416 composition (0 1 [32 65 57708]) fontified t) 19285 19293 (fontified t) 19293 19294 (face (rainbow-delimiters-depth-1-face) fontified t) 19294 19317 (face font-lock-string-face fontified t) 19317 19318 (face (rainbow-delimiters-depth-1-face) fontified t) 19318 19329 (fontified t) 19329 19330 (prettify-symbols-end 19462 prettify-symbols-start 19461 composition (0 1 [32 65 57708]) fontified t) 19330 19358 (fontified t) 19358 19363 (face font-lock-keyword-face fontified t) 19363 19364 (fontified t) 19364 19397 (face font-lock-type-face fontified t) 19397 19398 (face (rainbow-delimiters-depth-1-face) fontified t) 19398 19416 (fontified t) 19416 19417 (face (rainbow-delimiters-depth-1-face) fontified t) 19417 19418 (prettify-symbols-end 19550 prettify-symbols-start 19549 composition (0 1 [32 65 57708]) fontified t) 19418 19423 (fontified t) 19423 19425 (face font-lock-doc-face fontified t) 19425 19426 (face font-lock-doc-face syntax-table (15) fontified t) 19426 19471 (face font-lock-doc-face fontified t) 19471 19472 (face font-lock-doc-face syntax-table (15) fontified t) 19472 19474 (face font-lock-doc-face fontified t) 19474 19483 (fontified t) 19483 19484 (prettify-symbols-end 19616 prettify-symbols-start 19615 composition (0 1 [32 65 57708]) fontified t) 19484 19494 (fontified t) 19494 19495 (face (rainbow-delimiters-depth-1-face) fontified t) 19495 19517 (fontified t) 19517 19518 (face (rainbow-delimiters-depth-2-face) fontified t) 19518 19531 (fontified t) 19531 19532 (face font-lock-operator-face fontified t) 19532 19537 (face font-lock-constant-face fontified t) 19537 19538 (face (rainbow-delimiters-depth-2-face) fontified t) 19538 19539 (face (rainbow-delimiters-depth-1-face) fontified t) 19539 19544 (fontified t) 19544 19546 (face font-lock-string-face fontified t) 19546 19547 (face font-lock-string-face syntax-table (15) fontified t) 19547 19687 (face font-lock-string-face fontified t) 19687 19688 (face font-lock-string-face syntax-table (15) fontified t) 19688 19690 (face font-lock-string-face fontified t) 19690 19695 (fontified t) 19695 19707 (face font-lock-variable-name-face fontified t) 19707 19708 (fontified t) 19708 19709 (face font-lock-operator-face fontified t) 19709 19720 (fontified t) 19720 19721 (face (rainbow-delimiters-depth-1-face) fontified t) 19721 19726 (fontified t) 19726 19727 (face font-lock-operator-face fontified t) 19727 19734 (face font-lock-string-face fontified t) 19734 19735 (face (rainbow-delimiters-depth-1-face) fontified t) 19735 19738 (fontified t) 19738 19743 (face font-lock-keyword-face fontified t) 19743 19744 (fontified t) 19744 19771 (face font-lock-type-face fontified t) 19771 19772 (face (rainbow-delimiters-depth-1-face) fontified t) 19772 19789 (fontified t) 19789 19790 (face (rainbow-delimiters-depth-2-face) fontified t) 19790 19832 (fontified t) 19832 19833 (face (rainbow-delimiters-depth-3-face) fontified t) 19833 19866 (face font-lock-string-face fontified t) 19866 19867 (face (rainbow-delimiters-depth-3-face) fontified t) 19867 19868 (face (rainbow-delimiters-depth-2-face) fontified t) 19868 19869 (fontified t) 19869 19870 (face (rainbow-delimiters-depth-1-face) fontified t) 19870 19871 (prettify-symbols-end 20003 prettify-symbols-start 20002 composition (0 1 [32 65 57708]) fontified t) 19871 19876 (fontified t) 19876 19878 (face font-lock-doc-face fontified t) 19878 19879 (face font-lock-doc-face syntax-table (15) fontified t) 19879 20010 (face font-lock-doc-face fontified t) 20010 20011 (face font-lock-doc-face syntax-table (15) fontified t) 20011 20013 (face font-lock-doc-face fontified t) 20013 20025 (fontified t) 20025 20026 (prettify-symbols-end 20158 prettify-symbols-start 20157 composition (0 1 [32 65 57708]) fontified t) 20026 20034 (fontified t) 20034 20035 (face (rainbow-delimiters-depth-1-face) fontified t) 20035 20068 (face font-lock-string-face fontified t) 20068 20069 (face (rainbow-delimiters-depth-1-face) fontified t) 20069 20080 (fontified t) 20080 20081 (prettify-symbols-end 20213 prettify-symbols-start 20212 composition (0 1 [32 65 57708]) fontified t) 20081 20118 (fontified t) 20118 20123 (face font-lock-keyword-face fontified t) 20123 20124 (fontified t) 20124 20142 (face font-lock-type-face fontified t) 20142 20143 (face (rainbow-delimiters-depth-1-face) fontified t) 20143 20154 (fontified t) 20154 20155 (face (rainbow-delimiters-depth-2-face) fontified t) 20155 20162 (fontified t) 20162 20163 (face (rainbow-delimiters-depth-3-face) fontified t) 20163 20177 (face font-lock-string-face fontified t) 20177 20178 (face (rainbow-delimiters-depth-3-face) fontified t) 20178 20179 (face (rainbow-delimiters-depth-2-face) fontified t) 20179 20180 (face (rainbow-delimiters-depth-1-face) fontified t) 20180 20181 (prettify-symbols-end 20313 prettify-symbols-start 20312 composition (0 1 [32 65 57708]) fontified t) 20181 20186 (fontified t) 20186 20188 (face font-lock-doc-face fontified t) 20188 20189 (face font-lock-doc-face syntax-table (15) fontified t) 20189 20260 (face font-lock-doc-face fontified t) 20260 20261 (face font-lock-doc-face syntax-table (15) fontified t) 20261 20263 (face font-lock-doc-face fontified t) 20263 20275 (fontified t) 20275 20276 (prettify-symbols-end 20408 prettify-symbols-start 20407 composition (0 1 [32 65 57708]) fontified t) 20276 20284 (fontified t) 20284 20285 (face (rainbow-delimiters-depth-1-face) fontified t) 20285 20299 (face font-lock-string-face fontified t) 20299 20300 (face (rainbow-delimiters-depth-1-face) fontified t) 20300 20303 (fontified t) 20303 20308 (face font-lock-keyword-face fontified t) 20308 20309 (fontified t) 20309 20323 (face font-lock-type-face fontified t) 20323 20324 (face (rainbow-delimiters-depth-1-face) fontified t) 20324 20333 (fontified t) 20333 20334 (face (rainbow-delimiters-depth-1-face) fontified t) 20334 20335 (prettify-symbols-end 20467 prettify-symbols-start 20466 composition ((1 32 65 57708)) fontified t) 20335 20340 (fontified t) 20340 20342 (face font-lock-doc-face fontified t) 20342 20343 (face font-lock-doc-face syntax-table (15) fontified t) 20343 20377 (face font-lock-doc-face fontified t) 20377 20378 (face font-lock-doc-face syntax-table (15) fontified t) 20378 20380 (face font-lock-doc-face fontified t) 20380 20390 (fontified t) 20390 20391 (prettify-symbols-end 20523 prettify-symbols-start 20522 composition ((1 32 65 57708)) fontified t) 20391 20392 (fontified t) 20392 20395 (face font-lock-builtin-face fontified t) 20395 20400 (fontified t) 20400 20402 (face font-lock-string-face fontified t) 20402 20403 (face font-lock-string-face syntax-table (15) fontified t) 20403 20428 (face font-lock-string-face fontified t) 20428 20429 (face font-lock-string-face syntax-table (15) fontified t) 20429 20431 (face font-lock-string-face fontified t) 20431 20447 (fontified t) 20447 20448 (prettify-symbols-end 20580 prettify-symbols-start 20579 composition (0 1 [32 65 57708]) fontified t) 20448 20449 (fontified t) 20449 20452 (face font-lock-builtin-face fontified t) 20452 20453 (fontified t) 20453 20454 (face font-lock-operator-face fontified t) 20454 20455 (fontified t) 20455 20459 (face font-lock-constant-face fontified t) 20459 20460 (fontified t) 20460 20461 (face font-lock-operator-face fontified t) 20461 20462 (fontified t) 20462 20466 (face font-lock-constant-face fontified t) 20466 20471 (fontified t) 20471 20473 (face font-lock-doc-face fontified t) 20473 20474 (face font-lock-doc-face syntax-table (15) fontified t) 20474 20519 (face font-lock-doc-face fontified t) 20519 20520 (face font-lock-doc-face syntax-table (15) fontified t) 20520 20522 (face font-lock-doc-face fontified t) 20522 20535 (fontified t) 20535 20536 (prettify-symbols-end 20668 prettify-symbols-start 20667 composition (0 1 [32 65 57708]) fontified t) 20536 20537 (fontified t) 20537 20541 (face font-lock-builtin-face fontified t) 20541 20542 (fontified t) 20542 20543 (face font-lock-operator-face fontified t) 20543 20544 (fontified t) 20544 20548 (face font-lock-constant-face fontified t) 20548 20549 (fontified t) 20549 20550 (face font-lock-operator-face fontified t) 20550 20551 (fontified t) 20551 20555 (face font-lock-constant-face fontified t) 20555 20560 (fontified t) 20560 20562 (face font-lock-doc-face fontified t) 20562 20563 (face font-lock-doc-face syntax-table (15) fontified t) 20563 20602 (face font-lock-doc-face fontified t) 20602 20603 (face font-lock-doc-face syntax-table (15) fontified t) 20603 20605 (face font-lock-doc-face fontified t) 20605 20610 (fontified t) 20610 20622 (face font-lock-variable-name-face fontified t) 20622 20623 (fontified t) 20623 20624 (face font-lock-operator-face fontified t) 20624 20635 (fontified t) 20635 20636 (face (rainbow-delimiters-depth-1-face) fontified t) 20636 20641 (fontified t) 20641 20642 (face font-lock-operator-face fontified t) 20642 20649 (face font-lock-string-face fontified t) 20649 20650 (face (rainbow-delimiters-depth-1-face) fontified t) 20650 20653 (fontified t) 20653 20658 (face font-lock-keyword-face fontified t) 20658 20659 (fontified t) 20659 20665 (face font-lock-type-face fontified t) 20665 20666 (face (rainbow-delimiters-depth-1-face) fontified t) 20666 20678 (fontified t) 20678 20679 (face (rainbow-delimiters-depth-1-face) fontified t) 20679 20680 (prettify-symbols-end 20812 prettify-symbols-start 20811 composition (0 1 [32 65 57708]) fontified t) 20680 20685 (fontified t) 20685 20687 (face font-lock-doc-face fontified t) 20687 20688 (face font-lock-doc-face syntax-table (15) fontified t) 20688 20739 (face font-lock-doc-face fontified t) 20739 20740 (face font-lock-doc-face syntax-table (15) fontified t) 20740 20742 (face font-lock-doc-face fontified t) 20742 20751 (fontified t) 20751 20752 (prettify-symbols-end 20884 prettify-symbols-start 20883 composition (0 1 [32 65 57708]) fontified t) 20752 20762 (fontified t) 20762 20763 (face (rainbow-delimiters-depth-1-face) fontified t) 20763 20785 (fontified t) 20785 20786 (face (rainbow-delimiters-depth-2-face) fontified t) 20786 20801 (fontified t) 20801 20802 (face font-lock-operator-face fontified t) 20802 20803 (face (rainbow-delimiters-depth-3-face) fontified t) 20803 20811 (face font-lock-string-face fontified t) 20811 20812 (face (rainbow-delimiters-depth-3-face) fontified t) 20812 20827 (fontified t) 20827 20828 (face font-lock-operator-face fontified t) 20828 20833 (face font-lock-constant-face fontified t) 20833 20834 (face (rainbow-delimiters-depth-2-face) fontified t) 20834 20835 (face (rainbow-delimiters-depth-1-face) fontified t) 20835 20840 (fontified t) 20840 20842 (face font-lock-string-face fontified t) 20842 20843 (face font-lock-string-face syntax-table (15) fontified t) 20843 20888 (face font-lock-string-face fontified t) 20888 20889 (face font-lock-string-face syntax-table (15) fontified t) 20889 20891 (face font-lock-string-face fontified t) 20891 20907 (fontified t) 20907 20908 (prettify-symbols-end 21040 prettify-symbols-start 21039 composition (0 1 [32 65 57708]) fontified t) 20908 20909 (fontified t) 20909 20912 (face font-lock-builtin-face fontified t) 20912 20913 (fontified t) 20913 20914 (face font-lock-operator-face fontified t) 20914 20915 (fontified t) 20915 20919 (face font-lock-constant-face fontified t) 20919 20920 (fontified t) 20920 20921 (face font-lock-operator-face fontified t) 20921 20922 (fontified t) 20922 20926 (face font-lock-constant-face fontified t) 20926 20931 (fontified t) 20931 20933 (face font-lock-doc-face fontified t) 20933 20934 (face font-lock-doc-face syntax-table (15) fontified t) 20934 20987 (face font-lock-doc-face fontified t) 20987 20988 (face font-lock-doc-face syntax-table (15) fontified t) 20988 20990 (face font-lock-doc-face fontified t) 20990 21004 (fontified t) 21004 21005 (prettify-symbols-end 21137 prettify-symbols-start 21136 composition (0 1 [32 65 57708]) fontified t) 21005 21006 (fontified t) 21006 21010 (face font-lock-builtin-face fontified t) 21010 21011 (face (rainbow-delimiters-depth-1-face) fontified t) 21011 21025 (fontified t) 21025 21026 (face (rainbow-delimiters-depth-1-face) fontified t) 21026 21027 (fontified t) 21027 21028 (face font-lock-operator-face fontified t) 21028 21029 (fontified t) 21029 21033 (face font-lock-constant-face fontified t) 21033 21034 (fontified t) 21034 21035 (face font-lock-operator-face fontified t) 21035 21036 (fontified t) 21036 21040 (face font-lock-constant-face fontified t) 21040 21045 (fontified t) 21045 21047 (face font-lock-doc-face fontified t) 21047 21048 (face font-lock-doc-face syntax-table (15) fontified t) 21048 21101 (face font-lock-doc-face fontified t) 21101 21102 (face font-lock-doc-face syntax-table (15) fontified t) 21102 21104 (face font-lock-doc-face fontified t) 21104 21113 (fontified t) 21113 21114 (prettify-symbols-end 21246 prettify-symbols-start 21245 composition (0 1 [32 65 57708]) fontified t) 21114 21115 (fontified t) 21115 21119 (face font-lock-builtin-face fontified t) 21119 21120 (face (rainbow-delimiters-depth-1-face) fontified t) 21120 21123 (face font-lock-builtin-face fontified t) 21123 21128 (fontified t) 21128 21129 (face (rainbow-delimiters-depth-1-face) fontified t) 21129 21130 (fontified t) 21130 21131 (face font-lock-operator-face fontified t) 21131 21132 (fontified t) 21132 21136 (face font-lock-constant-face fontified t) 21136 21137 (fontified t) 21137 21138 (face font-lock-operator-face fontified t) 21138 21144 (fontified t) 21144 21145 (face (rainbow-delimiters-depth-1-face) fontified t) 21145 21150 (fontified t) 21150 21151 (face font-lock-operator-face fontified t) 21151 21158 (face font-lock-string-face fontified t) 21158 21167 (fontified t) 21167 21168 (face font-lock-operator-face fontified t) 21168 21172 (face font-lock-constant-face fontified t) 21172 21173 (face (rainbow-delimiters-depth-1-face) fontified t) 21173 21178 (fontified t) 21178 21180 (face font-lock-doc-face fontified t) 21180 21181 (face font-lock-doc-face syntax-table (15) fontified t) 21181 21408 (face font-lock-doc-face fontified t) 21408 21409 (face font-lock-doc-face syntax-table (15) fontified t) 21409 21411 (face font-lock-doc-face fontified t) 21411 21416 (fontified t) 21416 21428 (face font-lock-variable-name-face fontified t) 21428 21429 (fontified t) 21429 21430 (face font-lock-operator-face fontified t) 21430 21441 (fontified t) 21441 21442 (face (rainbow-delimiters-depth-1-face) fontified t) 21442 21447 (fontified t) 21447 21448 (face font-lock-operator-face fontified t) 21448 21455 (face font-lock-string-face fontified t) 21455 21456 (face (rainbow-delimiters-depth-1-face) fontified t) 21456 21459 (fontified t) 21459 21464 (face font-lock-keyword-face fontified t) 21464 21465 (fontified t) 21465 21482 (face font-lock-type-face fontified t) 21482 21483 (face (rainbow-delimiters-depth-1-face) fontified t) 21483 21493 (fontified t) 21493 21494 (face (rainbow-delimiters-depth-1-face) fontified t) 21494 21495 (prettify-symbols-end 21627 prettify-symbols-start 21626 composition (0 1 [32 65 57708]) fontified t) 21495 21500 (fontified t) 21500 21502 (face font-lock-doc-face fontified t) 21502 21503 (face font-lock-doc-face syntax-table (15) fontified t) 21503 21567 (face font-lock-doc-face fontified t) 21567 21568 (face font-lock-doc-face syntax-table (15) fontified t) 21568 21570 (face font-lock-doc-face fontified t) 21570 21583 (fontified t) 21583 21584 (prettify-symbols-end 21716 prettify-symbols-start 21715 composition (0 1 [32 65 57708]) fontified t) 21584 21585 (fontified t) 21585 21589 (face font-lock-builtin-face fontified t) 21589 21590 (face (rainbow-delimiters-depth-1-face) fontified t) 21590 21596 (fontified t) 21596 21597 (face (rainbow-delimiters-depth-1-face) fontified t) 21597 21600 (fontified t) 21600 21605 (face font-lock-keyword-face fontified t) 21605 21606 (fontified t) 21606 21628 (face font-lock-type-face fontified t) 21628 21629 (face (rainbow-delimiters-depth-1-face) fontified t) 21629 21642 (fontified t) 21642 21643 (face (rainbow-delimiters-depth-1-face) fontified t) 21643 21644 (prettify-symbols-end 21776 prettify-symbols-start 21775 composition (0 1 [32 65 57708]) fontified t) 21644 21649 (fontified t) 21649 21651 (face font-lock-doc-face fontified t) 21651 21652 (face font-lock-doc-face syntax-table (15) fontified t) 21652 21684 (face font-lock-doc-face fontified t) 21684 21685 (face font-lock-doc-face syntax-table (15) fontified t) 21685 21687 (face font-lock-doc-face fontified t) 21687 21697 (fontified t) 21697 21698 (prettify-symbols-end 21830 prettify-symbols-start 21829 composition (0 1 [32 65 57708]) fontified t) 21698 21699 (fontified t) 21699 21702 (face font-lock-builtin-face fontified t) 21702 21707 (fontified t) 21707 21709 (face font-lock-string-face fontified t) 21709 21710 (face font-lock-string-face syntax-table (15) fontified t) 21710 21752 (face font-lock-string-face fontified t) 21752 21753 (face font-lock-string-face syntax-table (15) fontified t) 21753 21755 (face font-lock-string-face fontified t) 21755 21769 (fontified t) 21769 21770 (prettify-symbols-end 21902 prettify-symbols-start 21901 composition (0 1 [32 65 57708]) fontified t) 21770 21771 (fontified t) 21771 21775 (face font-lock-builtin-face fontified t) 21775 21776 (face (rainbow-delimiters-depth-1-face) fontified t) 21776 21779 (face font-lock-builtin-face fontified t) 21779 21781 (fontified t) 21781 21784 (face font-lock-builtin-face fontified t) 21784 21785 (face (rainbow-delimiters-depth-1-face) fontified t) 21785 21786 (fontified t) 21786 21787 (face font-lock-operator-face fontified t) 21787 21788 (fontified t) 21788 21792 (face font-lock-constant-face fontified t) 21792 21793 (fontified t) 21793 21794 (face font-lock-operator-face fontified t) 21794 21795 (fontified t) 21795 21799 (face font-lock-constant-face fontified t) 21799 21804 (fontified t) 21804 21806 (face font-lock-doc-face fontified t) 21806 21807 (face font-lock-doc-face syntax-table (15) fontified t) 21807 21850 (face font-lock-doc-face fontified t) 21850 21851 (face font-lock-doc-face syntax-table (15) fontified t) 21851 21853 (face font-lock-doc-face fontified t) 21853 21858 (fontified t) 21858 21870 (face font-lock-variable-name-face fontified t) 21870 21871 (fontified t) 21871 21872 (face font-lock-operator-face fontified t) 21872 21883 (fontified t) 21883 21884 (face (rainbow-delimiters-depth-1-face) fontified t) 21884 21889 (fontified t) 21889 21890 (face font-lock-operator-face fontified t) 21890 21897 (face font-lock-string-face fontified t) 21897 21898 (face (rainbow-delimiters-depth-1-face) fontified t) 21898 21901 (fontified t) 21901 21906 (face font-lock-keyword-face fontified t) 21906 21907 (fontified t) 21907 21923 (face font-lock-type-face fontified t) 21923 21924 (face (rainbow-delimiters-depth-1-face) fontified t) 21924 21931 (fontified t) 21931 21932 (face (rainbow-delimiters-depth-2-face) fontified t) 21932 21963 (fontified t) 21963 21964 (face (rainbow-delimiters-depth-3-face) fontified t) 21964 21977 (face font-lock-string-face fontified t) 21977 21978 (face (rainbow-delimiters-depth-3-face) fontified t) 21978 21979 (face (rainbow-delimiters-depth-2-face) fontified t) 21979 21980 (face (rainbow-delimiters-depth-1-face) fontified t) 21980 21981 (prettify-symbols-end 22113 prettify-symbols-start 22112 composition (0 1 [32 65 57708]) fontified t) 21981 21986 (fontified t) 21986 21988 (face font-lock-doc-face fontified t) 21988 21989 (face font-lock-doc-face syntax-table (15) fontified t) 21989 22047 (face font-lock-doc-face fontified t) 22047 22048 (face font-lock-doc-face syntax-table (15) fontified t) 22048 22050 (face font-lock-doc-face fontified t) 22050 22062 (fontified t) 22062 22063 (prettify-symbols-end 22195 prettify-symbols-start 22194 composition (0 1 [32 65 57708]) fontified t) 22063 22071 (fontified t) 22071 22072 (face (rainbow-delimiters-depth-1-face) fontified t) 22072 22085 (face font-lock-string-face fontified t) 22085 22086 (face (rainbow-delimiters-depth-1-face) fontified t) 22086 22097 (fontified t) 22097 22098 (prettify-symbols-end 22230 prettify-symbols-start 22229 composition (0 1 [32 65 57708]) fontified t) 22098 22124 (fontified t) 22124 22129 (face font-lock-keyword-face fontified t) 22129 22130 (fontified t) 22130 22141 (face font-lock-type-face fontified t) 22141 22142 (face (rainbow-delimiters-depth-1-face) fontified t) 22142 22151 (fontified t) 22151 22152 (face (rainbow-delimiters-depth-1-face) fontified t) 22152 22153 (prettify-symbols-end 22285 prettify-symbols-start 22284 composition (0 1 [32 65 57708]) fontified t) 22153 22158 (fontified t) 22158 22160 (face font-lock-doc-face fontified t) 22160 22161 (face font-lock-doc-face syntax-table (15) fontified t) 22161 22188 (face font-lock-doc-face fontified t) 22188 22189 (face font-lock-doc-face syntax-table (15) fontified t) 22189 22191 (face font-lock-doc-face fontified t) 22191 22197 (fontified t) 22197 22201 (face font-lock-builtin-face fontified t) 22201 22202 (prettify-symbols-end 22334 prettify-symbols-start 22333 composition (0 1 [32 65 57708]) fontified t) 22202 22210 (fontified t) 22210 22211 (face (rainbow-delimiters-depth-1-face) fontified t) 22211 22217 (face font-lock-string-face fontified t) 22217 22218 (face (rainbow-delimiters-depth-1-face) fontified t) 22218 22227 (fontified t) 22227 22228 (prettify-symbols-end 22360 prettify-symbols-start 22359 composition (0 1 [32 65 57708]) fontified t) 22228 22229 (fontified t) 22229 22232 (face font-lock-builtin-face fontified t) 22232 22237 (fontified t) 22237 22239 (face font-lock-string-face fontified t) 22239 22240 (face font-lock-string-face syntax-table (15) fontified t) 22240 22272 (face font-lock-string-face fontified t) 22272 22273 (face font-lock-string-face syntax-table (15) fontified t) 22273 22275 (face font-lock-string-face fontified t) 22275 22291 (fontified t) 22291 22292 (prettify-symbols-end 22424 prettify-symbols-start 22423 composition (0 1 [32 65 57708]) fontified t) 22292 22305 (fontified t) 22305 22306 (face font-lock-operator-face fontified t) 22306 22307 (fontified t) 22307 22311 (face font-lock-constant-face fontified t) 22311 22312 (fontified t) 22312 22313 (face font-lock-operator-face fontified t) 22313 22314 (fontified t) 22314 22318 (face font-lock-constant-face fontified t) 22318 22327 (fontified t) 22327 22328 (prettify-symbols-end 22460 prettify-symbols-start 22459 composition (0 1 [32 65 57708]) fontified t) 22328 22329 (fontified t) 22329 22333 (face font-lock-builtin-face fontified t) 22333 22334 (face (rainbow-delimiters-depth-1-face) fontified t) 22334 22337 (face font-lock-builtin-face fontified t) 22337 22342 (fontified t) 22342 22343 (face (rainbow-delimiters-depth-1-face) fontified t) 22343 22344 (fontified t) 22344 22345 (face font-lock-operator-face fontified t) 22345 22346 (fontified t) 22346 22350 (face font-lock-constant-face fontified t) 22350 22351 (fontified t) 22351 22352 (face font-lock-operator-face fontified t) 22352 22358 (fontified t) 22358 22359 (face (rainbow-delimiters-depth-1-face) fontified t) 22359 22364 (fontified t) 22364 22365 (face font-lock-operator-face fontified t) 22365 22372 (face font-lock-string-face fontified t) 22372 22381 (fontified t) 22381 22382 (face font-lock-operator-face fontified t) 22382 22386 (face font-lock-constant-face fontified t) 22386 22387 (face (rainbow-delimiters-depth-1-face) fontified t) 22387 22392 (fontified t) 22392 22394 (face font-lock-doc-face fontified t) 22394 22395 (face font-lock-doc-face syntax-table (15) fontified t) 22395 22622 (face font-lock-doc-face fontified t) 22622 22623 (face font-lock-doc-face syntax-table (15) fontified t) 22623 22625 (face font-lock-doc-face fontified t) 22625 22630 (fontified t) 22630 22642 (face font-lock-variable-name-face fontified t) 22642 22643 (fontified t) 22643 22644 (face font-lock-operator-face fontified t) 22644 22655 (fontified t) 22655 22656 (face (rainbow-delimiters-depth-1-face) fontified t) 22656 22661 (fontified t) 22661 22662 (face font-lock-operator-face fontified t) 22662 22669 (face font-lock-string-face fontified t) 22669 22670 (face (rainbow-delimiters-depth-1-face) fontified t) 22670 22673 (fontified t) 22673 22678 (face font-lock-keyword-face fontified t) 22678 22679 (fontified t) 22679 22691 (face font-lock-type-face fontified t) 22691 22692 (face (rainbow-delimiters-depth-1-face) fontified t) 22692 22701 (fontified t) 22701 22702 (face (rainbow-delimiters-depth-1-face) fontified t) 22702 22703 (prettify-symbols-end 22835 prettify-symbols-start 22834 composition ((1 32 65 57708)) fontified t) 22703 22708 (fontified t) 22708 22710 (face font-lock-doc-face fontified t) 22710 22711 (face font-lock-doc-face syntax-table (15) fontified t) 22711 22739 (face font-lock-doc-face fontified t) 22739 22740 (face font-lock-doc-face syntax-table (15) fontified t) 22740 22742 (face font-lock-doc-face fontified t) 22742 22748 (fontified t) 22748 22752 (face font-lock-builtin-face fontified t) 22752 22753 (prettify-symbols-end 22885 prettify-symbols-start 22884 composition ((1 32 65 57708)) fontified t) 22753 22761 (fontified t) 22761 22762 (face (rainbow-delimiters-depth-1-face) fontified t) 22762 22769 (face font-lock-string-face fontified t) 22769 22770 (face (rainbow-delimiters-depth-1-face) fontified t) 22770 22779 (fontified t) 22779 22780 (prettify-symbols-end 22912 prettify-symbols-start 22911 composition ((1 32 65 57708)) fontified t) 22780 22781 (fontified t) 22781 22784 (face font-lock-builtin-face fontified t) 22784 22789 (fontified t) 22789 22791 (face font-lock-string-face fontified t) 22791 22792 (face font-lock-string-face syntax-table (15) fontified t) 22792 22822 (face font-lock-string-face fontified t) 22822 22823 (face font-lock-string-face syntax-table (15) fontified t) 22823 22825 (face font-lock-string-face fontified t) 22825 22838 (fontified t) 22838 22839 (prettify-symbols-end 22971 prettify-symbols-start 22970 composition ((1 32 65 57708)) fontified t) 22839 22840 (fontified t) 22840 22843 (face font-lock-builtin-face fontified t) 22843 22848 (fontified t) 22848 22850 (face font-lock-string-face fontified t) 22850 22851 (face font-lock-string-face syntax-table (15) fontified t) 22851 22947 (face font-lock-string-face fontified t) 22947 22948 (face font-lock-string-face syntax-table (15) fontified t) 22948 22950 (face font-lock-string-face fontified t) 22950 22966 (fontified t) 22966 22967 (prettify-symbols-end 23099 prettify-symbols-start 23098 composition ((1 32 65 57708)) fontified t) 22967 22980 (fontified t) 22980 22981 (face font-lock-operator-face fontified t) 22981 22982 (fontified t) 22982 22986 (face font-lock-constant-face fontified t) 22986 22987 (fontified t) 22987 22988 (face font-lock-operator-face fontified t) 22988 22989 (fontified t) 22989 22993 (face font-lock-constant-face fontified t) 22993 23002 (fontified t) 23002 23003 (prettify-symbols-end 23135 prettify-symbols-start 23134 composition ((1 32 65 57708)) fontified t) 23003 23004 (fontified t) 23004 23008 (face font-lock-builtin-face fontified t) 23008 23009 (face (rainbow-delimiters-depth-1-face) fontified t) 23009 23012 (face font-lock-builtin-face fontified t) 23012 23017 (fontified t) 23017 23018 (face (rainbow-delimiters-depth-1-face) fontified t) 23018 23019 (fontified t) 23019 23020 (face font-lock-operator-face fontified t) 23020 23021 (fontified t) 23021 23025 (face font-lock-constant-face fontified t) 23025 23026 (fontified t) 23026 23027 (face font-lock-operator-face fontified t) 23027 23033 (fontified t) 23033 23034 (face (rainbow-delimiters-depth-1-face) fontified t) 23034 23039 (fontified t) 23039 23040 (face font-lock-operator-face fontified t) 23040 23047 (face font-lock-string-face fontified t) 23047 23056 (fontified t) 23056 23057 (face font-lock-operator-face fontified t) 23057 23061 (face font-lock-constant-face fontified t) 23061 23062 (face (rainbow-delimiters-depth-1-face) fontified t) 23062 23067 (fontified t) 23067 23069 (face font-lock-doc-face fontified t) 23069 23070 (face font-lock-doc-face syntax-table (15) fontified t) 23070 23297 (face font-lock-doc-face fontified t) 23297 23298 (face font-lock-doc-face syntax-table (15) fontified t) 23298 23300 (face font-lock-doc-face fontified t) 23300 23305 (fontified t) 23305 23317 (face font-lock-variable-name-face fontified t) 23317 23318 (fontified t) 23318 23319 (face font-lock-operator-face fontified t) 23319 23330 (fontified t) 23330 23331 (face (rainbow-delimiters-depth-1-face) fontified t) 23331 23336 (fontified t) 23336 23337 (face font-lock-operator-face fontified t) 23337 23344 (face font-lock-string-face fontified t) 23344 23345 (face (rainbow-delimiters-depth-1-face) fontified t) 23345 23348 (fontified t) 23348 23353 (face font-lock-keyword-face fontified t) 23353 23354 (fontified t) 23354 23366 (face font-lock-type-face fontified t) 23366 23367 (face (rainbow-delimiters-depth-1-face) fontified t) 23367 23376 (fontified t) 23376 23377 (face (rainbow-delimiters-depth-1-face) fontified t) 23377 23378 (prettify-symbols-end 23510 prettify-symbols-start 23509 composition ((1 32 65 57708)) fontified t) 23378 23383 (fontified t) 23383 23385 (face font-lock-doc-face fontified t) 23385 23386 (face font-lock-doc-face syntax-table (15) fontified t) 23386 23414 (face font-lock-doc-face fontified t) 23414 23415 (face font-lock-doc-face syntax-table (15) fontified t) 23415 23417 (face font-lock-doc-face fontified t) 23417 23423 (fontified t) 23423 23427 (face font-lock-builtin-face fontified t) 23427 23428 (prettify-symbols-end 23560 prettify-symbols-start 23559 composition ((1 32 65 57708)) fontified t) 23428 23436 (fontified t) 23436 23437 (face (rainbow-delimiters-depth-1-face) fontified t) 23437 23444 (face font-lock-string-face fontified t) 23444 23445 (face (rainbow-delimiters-depth-1-face) fontified t) 23445 23454 (fontified t) 23454 23455 (prettify-symbols-end 23587 prettify-symbols-start 23586 composition ((1 32 65 57708)) fontified t) 23455 23456 (fontified t) 23456 23459 (face font-lock-builtin-face fontified t) 23459 23464 (fontified t) 23464 23466 (face font-lock-string-face fontified t) 23466 23467 (face font-lock-string-face syntax-table (15) fontified t) 23467 23497 (face font-lock-string-face fontified t) 23497 23498 (face font-lock-string-face syntax-table (15) fontified t) 23498 23500 (face font-lock-string-face fontified t) 23500 23513 (fontified t) 23513 23514 (prettify-symbols-end 23646 prettify-symbols-start 23645 composition ((1 32 65 57708)) fontified t) 23514 23515 (fontified t) 23515 23518 (face font-lock-builtin-face fontified t) 23518 23523 (fontified t) 23523 23525 (face font-lock-string-face fontified t) 23525 23526 (face font-lock-string-face syntax-table (15) fontified t) 23526 23622 (face font-lock-string-face fontified t) 23622 23623 (face font-lock-string-face syntax-table (15) fontified t) 23623 23625 (face font-lock-string-face fontified t) 23625 23641 (fontified t) 23641 23642 (prettify-symbols-end 23774 prettify-symbols-start 23773 composition ((1 32 65 57708)) fontified t) 23642 23655 (fontified t) 23655 23656 (face font-lock-operator-face fontified t) 23656 23657 (fontified t) 23657 23661 (face font-lock-constant-face fontified t) 23661 23662 (fontified t) 23662 23663 (face font-lock-operator-face fontified t) 23663 23664 (fontified t) 23664 23668 (face font-lock-constant-face fontified t) 23668 23677 (fontified t) 23677 23678 (prettify-symbols-end 23810 prettify-symbols-start 23809 composition ((1 32 65 57708)) fontified t) 23678 23679 (fontified t) 23679 23683 (face font-lock-builtin-face fontified t) 23683 23684 (face (rainbow-delimiters-depth-1-face) fontified t) 23684 23687 (face font-lock-builtin-face fontified t) 23687 23692 (fontified t) 23692 23693 (face (rainbow-delimiters-depth-1-face) fontified t) 23693 23694 (fontified t) 23694 23695 (face font-lock-operator-face fontified t) 23695 23696 (fontified t) 23696 23700 (face font-lock-constant-face fontified t) 23700 23701 (fontified t) 23701 23702 (face font-lock-operator-face fontified t) 23702 23708 (fontified t) 23708 23709 (face (rainbow-delimiters-depth-1-face) fontified t) 23709 23714 (fontified t) 23714 23715 (face font-lock-operator-face fontified t) 23715 23722 (face font-lock-string-face fontified t) 23722 23731 (fontified t) 23731 23732 (face font-lock-operator-face fontified t) 23732 23736 (face font-lock-constant-face fontified t) 23736 23737 (face (rainbow-delimiters-depth-1-face) fontified t) 23737 23742 (fontified t) 23742 23744 (face font-lock-doc-face fontified t) 23744 23745 (face font-lock-doc-face syntax-table (15) fontified t) 23745 23972 (face font-lock-doc-face fontified t) 23972 23973 (face font-lock-doc-face syntax-table (15) fontified t) 23973 23975 (face font-lock-doc-face fontified t) 23975 23980 (fontified t) 23980 23992 (face font-lock-variable-name-face fontified t) 23992 23993 (fontified t) 23993 23994 (face font-lock-operator-face fontified t) 23994 24005 (fontified t) 24005 24006 (face (rainbow-delimiters-depth-1-face) fontified t) 24006 24011 (fontified t) 24011 24012 (face font-lock-operator-face fontified t) 24012 24019 (face font-lock-string-face fontified t) 24019 24020 (face (rainbow-delimiters-depth-1-face) fontified t) 24020 24023 (fontified t) 24023 24028 (face font-lock-keyword-face fontified t) 24028 24029 (fontified t) 24029 24044 (face font-lock-type-face fontified t) 24044 24045 (face (rainbow-delimiters-depth-1-face) fontified t) 24045 24054 (fontified t) 24054 24055 (face (rainbow-delimiters-depth-1-face) fontified t) 24055 24056 (prettify-symbols-end 24188 prettify-symbols-start 24187 composition ((1 32 65 57708)) fontified t) 24056 24061 (fontified t) 24061 24063 (face font-lock-doc-face fontified t) 24063 24064 (face font-lock-doc-face syntax-table (15) fontified t) 24064 24122 (face font-lock-doc-face fontified t) 24122 24123 (face font-lock-doc-face syntax-table (15) fontified t) 24123 24125 (face font-lock-doc-face fontified t) 24125 24135 (fontified t) 24135 24136 (prettify-symbols-end 24268 prettify-symbols-start 24267 composition ((1 32 65 57708)) fontified t) 24136 24153 (fontified t) 24153 24154 (prettify-symbols-end 24286 prettify-symbols-start 24285 composition ((1 32 65 57708)) fontified t) 24154 24167 (fontified t) 24167 24168 (face font-lock-operator-face fontified t) 24168 24182 (fontified t) 24182 24183 (face font-lock-operator-face fontified t) 24183 24201 (fontified t) 24201 24213 (face font-lock-variable-name-face fontified t) 24213 24214 (fontified t) 24214 24215 (face font-lock-operator-face fontified t) 24215 24226 (fontified t) 24226 24227 (face (rainbow-delimiters-depth-1-face) fontified t) 24227 24232 (fontified t) 24232 24233 (face font-lock-operator-face fontified t) 24233 24240 (face font-lock-string-face fontified t) 24240 24241 (face (rainbow-delimiters-depth-1-face) fontified t) 24241 24244 (fontified t) 24244 24249 (face font-lock-keyword-face fontified t) 24249 24250 (fontified t) 24250 24266 (face font-lock-type-face fontified t) 24266 24267 (face (rainbow-delimiters-depth-1-face) fontified t) 24267 24276 (fontified t) 24276 24277 (face (rainbow-delimiters-depth-1-face) fontified t) 24277 24278 (prettify-symbols-end 24410 prettify-symbols-start 24409 composition ((1 32 65 57708)) fontified t) 24278 24283 (fontified t) 24283 24285 (face font-lock-doc-face fontified t) 24285 24286 (face font-lock-doc-face syntax-table (15) fontified t) 24286 24481 (face font-lock-doc-face fontified t) 24481 24482 (face font-lock-doc-face syntax-table (15) fontified t) 24482 24484 (face font-lock-doc-face fontified t) 24484 24490 (fontified t) 24490 24494 (face font-lock-builtin-face fontified t) 24494 24495 (prettify-symbols-end 24627 prettify-symbols-start 24626 composition ((1 32 65 57708)) fontified t) 24495 24503 (fontified t) 24503 24504 (face (rainbow-delimiters-depth-1-face) fontified t) 24504 24514 (face font-lock-string-face fontified t) 24514 24515 (face (rainbow-delimiters-depth-1-face) fontified t) 24515 24528 (fontified t) 24528 24529 (prettify-symbols-end 24661 prettify-symbols-start 24660 composition ((1 32 65 57708)) fontified t) 24529 24551 (fontified t) 24551 24552 (face font-lock-operator-face fontified t) 24552 24589 (fontified t) 24589 24590 (prettify-symbols-end 24722 prettify-symbols-start 24721 composition ((1 32 65 57708)) fontified t) 24590 24603 (fontified t) 24603 24604 (face font-lock-operator-face fontified t) 24604 24605 (fontified t) 24605 24609 (face font-lock-constant-face fontified t) 24609 24610 (fontified t) 24610 24611 (face font-lock-operator-face fontified t) 24611 24612 (fontified t) 24612 24616 (face font-lock-constant-face fontified t) 24616 24625 (fontified t) 24625 24626 (prettify-symbols-end 24758 prettify-symbols-start 24757 composition ((1 32 65 57708)) fontified t) 24626 24627 (fontified t) 24627 24631 (face font-lock-builtin-face fontified t) 24631 24632 (face (rainbow-delimiters-depth-1-face) fontified t) 24632 24635 (face font-lock-builtin-face fontified t) 24635 24640 (fontified t) 24640 24641 (face (rainbow-delimiters-depth-1-face) fontified t) 24641 24642 (fontified t) 24642 24643 (face font-lock-operator-face fontified t) 24643 24644 (fontified t) 24644 24648 (face font-lock-constant-face fontified t) 24648 24649 (fontified t) 24649 24650 (face font-lock-operator-face fontified t) 24650 24656 (fontified t) 24656 24657 (face (rainbow-delimiters-depth-1-face) fontified t) 24657 24662 (fontified t) 24662 24663 (face font-lock-operator-face fontified t) 24663 24670 (face font-lock-string-face fontified t) 24670 24679 (fontified t) 24679 24680 (face font-lock-operator-face fontified t) 24680 24684 (face font-lock-constant-face fontified t) 24684 24685 (face (rainbow-delimiters-depth-1-face) fontified t) 24685 24690 (fontified t) 24690 24692 (face font-lock-doc-face fontified t) 24692 24693 (face font-lock-doc-face syntax-table (15) fontified t) 24693 24920 (face font-lock-doc-face fontified t) 24920 24921 (face font-lock-doc-face syntax-table (15) fontified t) 24921 24923 (face font-lock-doc-face fontified t) 24923 24928 (fontified t) 24928 24940 (face font-lock-variable-name-face fontified t) 24940 24941 (fontified t) 24941 24942 (face font-lock-operator-face fontified t) 24942 24953 (fontified t) 24953 24954 (face (rainbow-delimiters-depth-1-face) fontified t) 24954 24959 (fontified t) 24959 24960 (face font-lock-operator-face fontified t) 24960 24967 (face font-lock-string-face fontified t) 24967 24968 (face (rainbow-delimiters-depth-1-face) fontified t) 24968 24971 (fontified t) 24971 24976 (face font-lock-keyword-face fontified t) 24976 24977 (fontified t) 24977 24989 (face font-lock-type-face fontified t) 24989 24990 (face (rainbow-delimiters-depth-1-face) fontified t) 24990 24998 (fontified t) 24998 24999 (face (rainbow-delimiters-depth-1-face) fontified t) 24999 25000 (prettify-symbols-end 25132 prettify-symbols-start 25131 composition ((1 32 65 57708)) fontified t) 25000 25005 (fontified t) 25005 25007 (face font-lock-doc-face fontified t) 25007 25008 (face font-lock-doc-face syntax-table (15) fontified t) 25008 25227 (face font-lock-doc-face fontified t) 25227 25228 (face font-lock-doc-face syntax-table (15) fontified t) 25228 25230 (face font-lock-doc-face fontified t) 25230 25236 (fontified t) 25236 25240 (face font-lock-builtin-face fontified t) 25240 25241 (prettify-symbols-end 25373 prettify-symbols-start 25372 composition ((1 32 65 57708)) fontified t) 25241 25249 (fontified t) 25249 25250 (face (rainbow-delimiters-depth-1-face) fontified t) 25250 25265 (face font-lock-string-face fontified t) 25265 25266 (face (rainbow-delimiters-depth-1-face) fontified t) 25266 25269 (fontified t) 25269 25281 (face font-lock-variable-name-face fontified t) 25281 25282 (fontified t) 25282 25283 (face font-lock-operator-face fontified t) 25283 25296 (fontified t) 25296 25297 (face font-lock-operator-face fontified t) 25297 25311 (fontified t) 25311 25312 (face font-lock-operator-face fontified t) 25312 25326 (fontified t) 25326 25327 (face font-lock-operator-face fontified t) 25327 25341 (fontified t) 25341 25342 (face font-lock-operator-face fontified t) 25342 25360 (fontified t) 25360 25362 (face font-lock-doc-face fontified t) 25362 25363 (face font-lock-doc-face syntax-table (15) fontified t) 25363 25424 (face font-lock-doc-face fontified t) 25424 25425 (face font-lock-doc-face syntax-table (15) fontified t) 25425 25427 (face font-lock-doc-face fontified t) 25427 25429 (fontified t) 25429 25436 (face font-lock-variable-name-face fontified t) 25436 25437 (prettify-symbols-end 25569 prettify-symbols-start 25568 composition ((1 32 65 57708)) fontified t) 25437 25448 (fontified t) 25448 25449 (face font-lock-operator-face fontified t) 25449 25463 (fontified t) 25463 25465 (face font-lock-comment-delimiter-face fontified t) 25465 25544 (face font-lock-comment-face fontified t) 25544 25546 (fontified t) 25546 25551 (face font-lock-keyword-face fontified t) 25551 25552 (fontified t) 25552 25565 (face font-lock-type-face fontified t) 25565 25566 (face (rainbow-delimiters-depth-1-face) fontified t) 25566 25575 (fontified t) 25575 25576 (face (rainbow-delimiters-depth-1-face) fontified t) 25576 25577 (prettify-symbols-end 25709 prettify-symbols-start 25708 composition (0 1 [32 65 57708]) fontified t) 25577 25582 (fontified t) 25582 25584 (face font-lock-doc-face fontified t) 25584 25585 (face font-lock-doc-face syntax-table (15) fontified t) 25585 25634 (face font-lock-doc-face fontified t) 25634 25635 (face font-lock-doc-face syntax-table (15) fontified t) 25635 25637 (face font-lock-doc-face fontified t) 25637 25647 (fontified t) 25647 25648 (prettify-symbols-end 25780 prettify-symbols-start 25779 composition (0 1 [32 65 57708]) fontified t) 25648 25665 (fontified t) 25665 25666 (prettify-symbols-end 25798 prettify-symbols-start 25797 composition (0 1 [32 65 57708]) fontified t) 25666 25684 (fontified t) 25684 25696 (face font-lock-variable-name-face fontified t) 25696 25697 (fontified t) 25697 25698 (face font-lock-operator-face fontified t) 25698 25709 (fontified t) 25709 25710 (face (rainbow-delimiters-depth-1-face) fontified t) 25710 25715 (fontified t) 25715 25716 (face font-lock-operator-face fontified t) 25716 25723 (face font-lock-string-face fontified t) 25723 25724 (face (rainbow-delimiters-depth-1-face) fontified t) 25724 25727 (fontified t) 25727 25732 (face font-lock-keyword-face fontified t) 25732 25733 (fontified t) 25733 25748 (face font-lock-type-face fontified t) 25748 25749 (face (rainbow-delimiters-depth-1-face) fontified t) 25749 25755 (fontified t) 25755 25756 (face (rainbow-delimiters-depth-1-face) fontified t) 25756 25757 (prettify-symbols-end 25889 prettify-symbols-start 25888 composition (0 1 [32 65 57708]) fontified t) 25757 25762 (fontified t) 25762 25764 (face font-lock-doc-face fontified t) 25764 25765 (face font-lock-doc-face syntax-table (15) fontified t) 25765 25828 (face font-lock-doc-face fontified t) 25828 25829 (face font-lock-doc-face syntax-table (15) fontified t) 25829 25831 (face font-lock-doc-face fontified t) 25831 25848 (fontified t) 25848 25849 (prettify-symbols-end 25981 prettify-symbols-start 25980 composition (0 1 [32 65 57708]) fontified t) 25849 25850 (fontified t) 25850 25853 (face font-lock-builtin-face fontified t) 25853 25854 (fontified t) 25854 25855 (face font-lock-operator-face fontified t) 25855 25856 (fontified t) 25856 25860 (face font-lock-constant-face fontified t) 25860 25861 (fontified t) 25861 25862 (face font-lock-operator-face fontified t) 25862 25863 (fontified t) 25863 25867 (face font-lock-constant-face fontified t) 25867 25872 (fontified t) 25872 25874 (face font-lock-doc-face fontified t) 25874 25875 (face font-lock-doc-face syntax-table (15) fontified t) 25875 25914 (face font-lock-doc-face fontified t) 25914 25915 (face font-lock-doc-face syntax-table (15) fontified t) 25915 25917 (face font-lock-doc-face fontified t) 25917 25930 (fontified t) 25930 25931 (prettify-symbols-end 26063 prettify-symbols-start 26062 composition (0 1 [32 65 57708]) fontified t) 25931 25932 (fontified t) 25932 25936 (face font-lock-builtin-face fontified t) 25936 25937 (face (rainbow-delimiters-depth-1-face) fontified t) 25937 25950 (fontified t) 25950 25951 (face (rainbow-delimiters-depth-1-face) fontified t) 25951 25954 (fontified t) 25954 25959 (face font-lock-keyword-face fontified t) 25959 25960 (fontified t) 25960 25989 (face font-lock-type-face fontified t) 25989 25990 (face (rainbow-delimiters-depth-1-face) fontified t) 25990 26007 (fontified t) 26007 26008 (face (rainbow-delimiters-depth-2-face) fontified t) 26008 26027 (fontified t) 26027 26028 (face font-lock-operator-face fontified t) 26028 26029 (fontified t) 26029 26033 (face font-lock-constant-face fontified t) 26033 26042 (fontified t) 26042 26043 (face (rainbow-delimiters-depth-3-face) fontified t) 26043 26079 (face font-lock-string-face fontified t) 26079 26080 (face (rainbow-delimiters-depth-3-face) fontified t) 26080 26081 (face (rainbow-delimiters-depth-2-face) fontified t) 26081 26082 (fontified t) 26082 26083 (face (rainbow-delimiters-depth-1-face) fontified t) 26083 26084 (prettify-symbols-end 26216 prettify-symbols-start 26215 composition (0 1 [32 65 57708]) fontified t) 26084 26089 (fontified t) 26089 26091 (face font-lock-doc-face fontified t) 26091 26092 (face font-lock-doc-face syntax-table (15) fontified t) 26092 26222 (face font-lock-doc-face fontified t) 26222 26223 (face font-lock-doc-face syntax-table (15) fontified t) 26223 26225 (face font-lock-doc-face fontified t) 26225 26237 (fontified t) 26237 26238 (prettify-symbols-end 26370 prettify-symbols-start 26369 composition (0 1 [32 65 57708]) fontified t) 26238 26246 (fontified t) 26246 26247 (face (rainbow-delimiters-depth-1-face) fontified t) 26247 26283 (face font-lock-string-face fontified t) 26283 26284 (face (rainbow-delimiters-depth-1-face) fontified t) 26284 26295 (fontified t) 26295 26296 (prettify-symbols-end 26428 prettify-symbols-start 26427 composition (0 1 [32 65 57708]) fontified t) 26296 26316 (fontified t) 26316 26317 (face font-lock-operator-face fontified t) 26317 26318 (fontified t) 26318 26322 (face font-lock-constant-face fontified t) 26322 26323 (fontified t) 26323 26324 (face font-lock-operator-face fontified t) 26324 26325 (fontified t) 26325 26329 (face font-lock-constant-face fontified t) 26329 26332 (fontified t) 26332 26337 (face font-lock-keyword-face fontified t) 26337 26338 (fontified t) 26338 26354 (face font-lock-type-face fontified t) 26354 26355 (face (rainbow-delimiters-depth-1-face) fontified t) 26355 26366 (fontified t) 26366 26367 (face (rainbow-delimiters-depth-2-face) fontified t) 26367 26374 (fontified t) 26374 26375 (face (rainbow-delimiters-depth-3-face) fontified t) 26375 26387 (face font-lock-string-face fontified t) 26387 26388 (face (rainbow-delimiters-depth-3-face) fontified t) 26388 26389 (face (rainbow-delimiters-depth-2-face) fontified t) 26389 26390 (face (rainbow-delimiters-depth-1-face) fontified t) 26390 26391 (prettify-symbols-end 26523 prettify-symbols-start 26522 composition (0 1 [32 65 57708]) fontified t) 26391 26396 (fontified t) 26396 26398 (face font-lock-doc-face fontified t) 26398 26399 (face font-lock-doc-face syntax-table (15) fontified t) 26399 26462 (face font-lock-doc-face fontified t) 26462 26463 (face font-lock-doc-face syntax-table (15) fontified t) 26463 26465 (face font-lock-doc-face fontified t) 26465 26477 (fontified t) 26477 26478 (prettify-symbols-end 26610 prettify-symbols-start 26609 composition (0 1 [32 65 57708]) fontified t) 26478 26486 (fontified t) 26486 26487 (face (rainbow-delimiters-depth-1-face) fontified t) 26487 26499 (face font-lock-string-face fontified t) 26499 26500 (face (rainbow-delimiters-depth-1-face) fontified t) 26500 26503 (fontified t) 26503 26508 (face font-lock-keyword-face fontified t) 26508 26509 (fontified t) 26509 26524 (face font-lock-type-face fontified t) 26524 26525 (face (rainbow-delimiters-depth-1-face) fontified t) 26525 26534 (fontified t) 26534 26535 (face (rainbow-delimiters-depth-1-face) fontified t) 26535 26536 (prettify-symbols-end 26668 prettify-symbols-start 26667 composition (0 1 [32 65 57708]) fontified t) 26536 26541 (fontified t) 26541 26543 (face font-lock-doc-face fontified t) 26543 26544 (face font-lock-doc-face syntax-table (15) fontified t) 26544 26909 (face font-lock-doc-face fontified t) 26909 26910 (face font-lock-doc-face syntax-table (15) fontified t) 26910 26912 (face font-lock-doc-face fontified t) 26912 26923 (fontified t) 26923 26924 (prettify-symbols-end 27056 prettify-symbols-start 27055 composition (0 1 [32 65 57708]) fontified t) 26924 26925 (fontified t) 26925 26928 (face font-lock-builtin-face fontified t) 26928 26929 (fontified t) 26929 26930 (face font-lock-operator-face fontified t) 26930 26931 (fontified t) 26931 26935 (face font-lock-constant-face fontified t) 26935 26936 (fontified t) 26936 26937 (face font-lock-operator-face fontified t) 26937 26938 (fontified t) 26938 26942 (face font-lock-constant-face fontified t) 26942 26947 (fontified t) 26947 26949 (face font-lock-doc-face fontified t) 26949 26950 (face font-lock-doc-face syntax-table (15) fontified t) 26950 26986 (face font-lock-doc-face fontified t) 26986 26987 (face font-lock-doc-face syntax-table (15) fontified t) 26987 26989 (face font-lock-doc-face fontified t) 26989 27007 (fontified t) 27007 27008 (prettify-symbols-end 27140 prettify-symbols-start 27139 composition (0 1 [32 65 57708]) fontified t) 27008 27009 (fontified t) 27009 27013 (face font-lock-builtin-face fontified t) 27013 27014 (fontified t) 27014 27015 (face font-lock-operator-face fontified t) 27015 27016 (fontified t) 27016 27020 (face font-lock-constant-face fontified t) 27020 27021 (fontified t) 27021 27022 (face font-lock-operator-face fontified t) 27022 27023 (fontified t) 27023 27027 (face font-lock-constant-face fontified t) 27027 27032 (fontified t) 27032 27034 (face font-lock-doc-face fontified t) 27034 27035 (face font-lock-doc-face syntax-table (15) fontified t) 27035 27114 (face font-lock-doc-face fontified t) 27114 27115 (face font-lock-doc-face syntax-table (15) fontified t) 27115 27117 (face font-lock-doc-face fontified t) 27117 27138 (fontified t) 27138 27139 (prettify-symbols-end 27271 prettify-symbols-start 27270 composition (0 1 [32 65 57708]) fontified t) 27139 27140 (fontified t) 27140 27144 (face font-lock-builtin-face fontified t) 27144 27145 (fontified t) 27145 27146 (face font-lock-operator-face fontified t) 27146 27147 (fontified t) 27147 27151 (face font-lock-constant-face fontified t) 27151 27152 (fontified t) 27152 27153 (face font-lock-operator-face fontified t) 27153 27154 (fontified t) 27154 27158 (face font-lock-constant-face fontified t) 27158 27163 (fontified t) 27163 27165 (face font-lock-doc-face fontified t) 27165 27166 (face font-lock-doc-face syntax-table (15) fontified t) 27166 27386 (face font-lock-doc-face fontified t) 27386 27387 (face font-lock-doc-face syntax-table (15) fontified t) 27387 27389 (face font-lock-doc-face fontified t) 27389 27409 (fontified t) 27409 27410 (prettify-symbols-end 27542 prettify-symbols-start 27541 composition ((1 32 65 57708)) fontified t) 27410 27411 (fontified t) 27411 27415 (face font-lock-builtin-face fontified t) 27415 27416 (fontified t) 27416 27417 (face font-lock-operator-face fontified t) 27417 27418 (fontified t) 27418 27422 (face font-lock-constant-face fontified t) 27422 27423 (fontified t) 27423 27424 (face font-lock-operator-face fontified t) 27424 27425 (fontified t) 27425 27429 (face font-lock-constant-face fontified t) 27429 27434 (fontified t) 27434 27436 (face font-lock-doc-face fontified t) 27436 27437 (face font-lock-doc-face syntax-table (15) fontified t) 27437 27653 (face font-lock-doc-face fontified t) 27653 27654 (face font-lock-doc-face syntax-table (15) fontified t) 27654 27656 (face font-lock-doc-face fontified t) 27656 27675 (fontified t) 27675 27676 (prettify-symbols-end 27808 prettify-symbols-start 27807 composition ((1 32 65 57708)) fontified t) 27676 27677 (fontified t) 27677 27681 (face font-lock-builtin-face fontified t) 27681 27682 (fontified t) 27682 27683 (face font-lock-operator-face fontified t) 27683 27684 (fontified t) 27684 27688 (face font-lock-constant-face fontified t) 27688 27689 (fontified t) 27689 27690 (face font-lock-operator-face fontified t) 27690 27691 (fontified t) 27691 27695 (face font-lock-constant-face fontified t) 27695 27700 (fontified t) 27700 27702 (face font-lock-doc-face fontified t) 27702 27703 (face font-lock-doc-face syntax-table (15) fontified t) 27703 27962 (face font-lock-doc-face fontified t) 27962 27963 (face font-lock-doc-face syntax-table (15) fontified t) 27963 27965 (face font-lock-doc-face fontified t) 27965 27970 (fontified t) 27970 27982 (face font-lock-variable-name-face fontified t) 27982 27983 (fontified t) 27983 27984 (face font-lock-operator-face fontified t) 27984 27995 (fontified t) 27995 27996 (face (rainbow-delimiters-depth-1-face) fontified t) 27996 28001 (fontified t) 28001 28002 (face font-lock-operator-face fontified t) 28002 28009 (face font-lock-string-face fontified t) 28009 28010 (face (rainbow-delimiters-depth-1-face) fontified t) 28010 28013 (fontified t) 28013 28018 (face font-lock-keyword-face fontified t) 28018 28019 (fontified t) 28019 28023 (face font-lock-type-face fontified t) 28023 28024 (face (rainbow-delimiters-depth-1-face) fontified t) 28024 28036 (fontified t) 28036 28037 (face (rainbow-delimiters-depth-1-face) fontified t) 28037 28038 (prettify-symbols-end 28170 prettify-symbols-start 28169 composition (0 1 [32 65 57708]) fontified t) 28038 28043 (fontified t) 28043 28045 (face font-lock-doc-face fontified t) 28045 28046 (face font-lock-doc-face syntax-table (15) fontified t) 28046 28088 (face font-lock-doc-face fontified t) 28088 28089 (face font-lock-doc-face syntax-table (15) fontified t) 28089 28091 (face font-lock-doc-face fontified t) 28091 28100 (fontified t) 28100 28101 (prettify-symbols-end 28233 prettify-symbols-start 28232 composition (0 1 [32 65 57708]) fontified t) 28101 28111 (fontified t) 28111 28112 (face (rainbow-delimiters-depth-1-face) fontified t) 28112 28134 (fontified t) 28134 28135 (face (rainbow-delimiters-depth-2-face) fontified t) 28135 28150 (fontified t) 28150 28151 (face font-lock-operator-face fontified t) 28151 28152 (face (rainbow-delimiters-depth-3-face) fontified t) 28152 28158 (face font-lock-string-face fontified t) 28158 28159 (face (rainbow-delimiters-depth-3-face) fontified t) 28159 28174 (fontified t) 28174 28175 (face font-lock-operator-face fontified t) 28175 28180 (face font-lock-constant-face fontified t) 28180 28181 (face (rainbow-delimiters-depth-2-face) fontified t) 28181 28182 (face (rainbow-delimiters-depth-1-face) fontified t) 28182 28187 (fontified t) 28187 28189 (face font-lock-string-face fontified t) 28189 28190 (face font-lock-string-face syntax-table (15) fontified t) 28190 28231 (face font-lock-string-face fontified t) 28231 28232 (face font-lock-string-face syntax-table (15) fontified t) 28232 28234 (face font-lock-string-face fontified t) 28234 28250 (fontified t) 28250 28251 (prettify-symbols-end 28383 prettify-symbols-start 28382 composition (0 1 [32 65 57708]) fontified t) 28251 28252 (fontified t) 28252 28255 (face font-lock-builtin-face fontified t) 28255 28256 (fontified t) 28256 28257 (face font-lock-operator-face fontified t) 28257 28258 (fontified t) 28258 28262 (face font-lock-constant-face fontified t) 28262 28263 (fontified t) 28263 28264 (face font-lock-operator-face fontified t) 28264 28265 (fontified t) 28265 28269 (face font-lock-constant-face fontified t) 28269 28274 (fontified t) 28274 28276 (face font-lock-doc-face fontified t) 28276 28277 (face font-lock-doc-face syntax-table (15) fontified t) 28277 28318 (face font-lock-doc-face fontified t) 28318 28319 (face font-lock-doc-face syntax-table (15) fontified t) 28319 28321 (face font-lock-doc-face fontified t) 28321 28337 (fontified t) 28337 28338 (prettify-symbols-end 28470 prettify-symbols-start 28469 composition (0 1 [32 65 57708]) fontified t) 28338 28339 (fontified t) 28339 28343 (face font-lock-builtin-face fontified t) 28343 28344 (face (rainbow-delimiters-depth-1-face) fontified t) 28344 28347 (face font-lock-builtin-face fontified t) 28347 28352 (fontified t) 28352 28353 (face (rainbow-delimiters-depth-1-face) fontified t) 28353 28358 (fontified t) 28358 28360 (face font-lock-string-face fontified t) 28360 28361 (face font-lock-string-face syntax-table (15) fontified t) 28361 28428 (face font-lock-string-face fontified t) 28428 28429 (face font-lock-string-face syntax-table (15) fontified t) 28429 28431 (face font-lock-string-face fontified t) 28431 28448 (fontified t) 28448 28449 (prettify-symbols-end 28581 prettify-symbols-start 28580 composition (0 1 [32 65 57708]) fontified t) 28449 28450 (fontified t) 28450 28454 (face font-lock-builtin-face fontified t) 28454 28455 (face (rainbow-delimiters-depth-1-face) fontified t) 28455 28458 (face font-lock-builtin-face fontified t) 28458 28463 (fontified t) 28463 28464 (face (rainbow-delimiters-depth-1-face) fontified t) 28464 28465 (fontified t) 28465 28466 (face font-lock-operator-face fontified t) 28466 28467 (fontified t) 28467 28471 (face font-lock-constant-face fontified t) 28471 28472 (fontified t) 28472 28473 (face font-lock-operator-face fontified t) 28473 28474 (fontified t) 28474 28478 (face font-lock-constant-face fontified t) 28478 28483 (fontified t) 28483 28485 (face font-lock-doc-face fontified t) 28485 28486 (face font-lock-doc-face syntax-table (15) fontified t) 28486 28635 (face font-lock-doc-face fontified t) 28635 28636 (face font-lock-doc-face syntax-table (15) fontified t) 28636 28638 (face font-lock-doc-face fontified t) 28638 28654 (fontified t) 28654 28655 (prettify-symbols-end 28787 prettify-symbols-start 28786 composition (0 1 [32 65 57708]) fontified t) 28655 28672 (fontified t) 28672 28673 (face font-lock-operator-face fontified t) 28673 28674 (fontified t) 28674 28678 (face font-lock-constant-face fontified t) 28678 28679 (fontified t) 28679 28680 (face font-lock-operator-face fontified t) 28680 28681 (fontified t) 28681 28685 (face font-lock-constant-face fontified t) 28685 28690 (fontified t) 28690 28692 (face font-lock-doc-face fontified t) 28692 28693 (face font-lock-doc-face syntax-table (15) fontified t) 28693 28730 (face font-lock-doc-face fontified t) 28730 28731 (face font-lock-doc-face syntax-table (15) fontified t) 28731 28733 (face font-lock-doc-face fontified t) 28733 28742 (fontified t) 28742 28743 (prettify-symbols-end 28875 prettify-symbols-start 28874 composition (0 1 [32 65 57708]) fontified t) 28743 28744 (fontified t) 28744 28748 (face font-lock-builtin-face fontified t) 28748 28749 (face (rainbow-delimiters-depth-1-face) fontified t) 28749 28752 (face font-lock-builtin-face fontified t) 28752 28757 (fontified t) 28757 28758 (face (rainbow-delimiters-depth-1-face) fontified t) 28758 28759 (fontified t) 28759 28760 (face font-lock-operator-face fontified t) 28760 28761 (fontified t) 28761 28765 (face font-lock-constant-face fontified t) 28765 28766 (fontified t) 28766 28767 (face font-lock-operator-face fontified t) 28767 28773 (fontified t) 28773 28774 (face (rainbow-delimiters-depth-1-face) fontified t) 28774 28779 (fontified t) 28779 28780 (face font-lock-operator-face fontified t) 28780 28787 (face font-lock-string-face fontified t) 28787 28796 (fontified t) 28796 28797 (face font-lock-operator-face fontified t) 28797 28801 (face font-lock-constant-face fontified t) 28801 28802 (face (rainbow-delimiters-depth-1-face) fontified t) 28802 28807 (fontified t) 28807 28809 (face font-lock-doc-face fontified t) 28809 28810 (face font-lock-doc-face syntax-table (15) fontified t) 28810 29037 (face font-lock-doc-face fontified t) 29037 29038 (face font-lock-doc-face syntax-table (15) fontified t) 29038 29040 (face font-lock-doc-face fontified t) 29040 29045 (fontified t) 29045 29057 (face font-lock-variable-name-face fontified t) 29057 29058 (fontified t) 29058 29059 (face font-lock-operator-face fontified t) 29059 29070 (fontified t) 29070 29071 (face (rainbow-delimiters-depth-1-face) fontified t) 29071 29076 (fontified t) 29076 29077 (face font-lock-operator-face fontified t) 29077 29084 (face font-lock-string-face fontified t) 29084 29085 (face (rainbow-delimiters-depth-1-face) fontified t)) . 132) (undo-tree-id0 . -3484) (undo-tree-id1 . -7754) (undo-tree-id2 . -29085) (t 26765 23376 312104 234000)) nil (26766 43722 623010 0) 0 nil] [nil nil ((42087 . 42088) (t 26765 23376 312104 234000)) ((#("n" 0 1 (ws-butler-chg chg fontified t)) . 42087)) (26766 23935 746852 0) 0 nil] [nil nil ((1 . 2) (t 26765 23376 312104 234000)) ((#(" -" 0 1 (ws-butler-chg chg fontified t)) . 1) (undo-tree-id0 . -1) (undo-tree-id1 . -1) (undo-tree-id2 . -1) (undo-tree-id3 . -1)) (26766 23908 526851 0) 0 nil]) -nil -nil -nil diff --git a/src/mcp/server/fastmcp/prompts/base.py b/src/mcp/server/fastmcp/prompts/base.py index e42928c94..4a19c0ed0 100644 --- a/src/mcp/server/fastmcp/prompts/base.py +++ b/src/mcp/server/fastmcp/prompts/base.py @@ -5,7 +5,7 @@ from typing import Any, Literal import pydantic_core -from pydantic import BaseModel, Field, TypeAdapter, validate_call +from pydantic import AnyUrl, BaseModel, Field, TypeAdapter, validate_call from mcp.types import PROMPT_SCHEME, ContentBlock, TextContent @@ -58,7 +58,7 @@ class Prompt(BaseModel): """A prompt template that can be rendered with parameters.""" name: str = Field(description="Name of the prompt") - uri: str = Field(description="URI of the prompt") + uri: AnyUrl = Field(description="URI of the prompt") title: str | None = Field(None, description="Human-readable title of the prompt") description: str | None = Field(None, description="Description of what the prompt does") arguments: list[PromptArgument] | None = Field(None, description="Arguments that can be passed to the prompt") @@ -67,7 +67,7 @@ class Prompt(BaseModel): def __init__(self, **data: Any) -> None: """Initialize Prompt, generating URI from name if not provided.""" if "uri" not in data and "name" in data: - data["uri"] = f"{PROMPT_SCHEME}/{data['name']}" + data["uri"] = AnyUrl(f"{PROMPT_SCHEME}/{data['name']}") super().__init__(**data) @classmethod diff --git a/src/mcp/server/fastmcp/prompts/manager.py b/src/mcp/server/fastmcp/prompts/manager.py index 45ee7f264..8a74a63a9 100644 --- a/src/mcp/server/fastmcp/prompts/manager.py +++ b/src/mcp/server/fastmcp/prompts/manager.py @@ -1,6 +1,8 @@ """Prompt management functionality.""" -from typing import Any +from typing import Any, overload + +from pydantic import AnyUrl from mcp.server.fastmcp.prompts.base import Message, Prompt from mcp.server.fastmcp.uri_utils import filter_by_uri_paths, normalize_to_prompt_uri @@ -20,15 +22,28 @@ def _normalize_to_uri(self, name_or_uri: str) -> str: """Convert name to URI if needed.""" return normalize_to_prompt_uri(name_or_uri) - def get_prompt(self, name: str) -> Prompt | None: + @overload + def get_prompt(self, name_or_uri: str) -> Prompt | None: + """Get prompt by name.""" + ... + + @overload + def get_prompt(self, name_or_uri: AnyUrl) -> Prompt | None: + """Get prompt by URI.""" + ... + + def get_prompt(self, name_or_uri: AnyUrl | str) -> Prompt | None: """Get prompt by name or URI.""" - uri = self._normalize_to_uri(name) + if isinstance(name_or_uri, AnyUrl): + return self._prompts.get(str(name_or_uri)) + uri = self._normalize_to_uri(name_or_uri) return self._prompts.get(uri) - def list_prompts(self, uri_paths: list[str] | None = None) -> list[Prompt]: + def list_prompts(self, uri_paths: list[AnyUrl] | None = None) -> list[Prompt]: """List all registered prompts, optionally filtered by URI paths.""" prompts = list(self._prompts.values()) - prompts = filter_by_uri_paths(prompts, uri_paths, lambda p: p.uri) + if uri_paths: + prompts = filter_by_uri_paths(prompts, uri_paths) logger.debug("Listing prompts", extra={"count": len(prompts), "uri_paths": uri_paths}) return prompts @@ -40,19 +55,29 @@ def add_prompt( logger.debug(f"Adding prompt: {prompt.name} with URI: {prompt.uri}") # Check for duplicates - existing = self._prompts.get(prompt.uri) + existing = self._prompts.get(str(prompt.uri)) if existing: if self.warn_on_duplicate_prompts: logger.warning(f"Prompt already exists: {prompt.uri}") return existing - self._prompts[prompt.uri] = prompt + self._prompts[str(prompt.uri)] = prompt return prompt - async def render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> list[Message]: + @overload + async def render_prompt(self, name_or_uri: str, arguments: dict[str, Any] | None = None) -> list[Message]: """Render a prompt by name with arguments.""" - prompt = self.get_prompt(name) + ... + + @overload + async def render_prompt(self, name_or_uri: AnyUrl, arguments: dict[str, Any] | None = None) -> list[Message]: + """Render a prompt by URI with arguments.""" + ... + + async def render_prompt(self, name_or_uri: AnyUrl | str, arguments: dict[str, Any] | None = None) -> list[Message]: + """Render a prompt by name or URI with arguments.""" + prompt = self.get_prompt(name_or_uri) if not prompt: - raise ValueError(f"Unknown prompt: {name}") + raise ValueError(f"Unknown prompt: {name_or_uri}") return await prompt.render(arguments) diff --git a/src/mcp/server/fastmcp/prompts/prompt_manager.py b/src/mcp/server/fastmcp/prompts/prompt_manager.py index 772d00c22..92b329d7c 100644 --- a/src/mcp/server/fastmcp/prompts/prompt_manager.py +++ b/src/mcp/server/fastmcp/prompts/prompt_manager.py @@ -1,5 +1,7 @@ """Prompt management functionality.""" +from pydantic import AnyUrl + from mcp.server.fastmcp.prompts.base import Prompt from mcp.server.fastmcp.uri_utils import filter_by_uri_paths, normalize_to_prompt_uri from mcp.server.fastmcp.utilities.logging import get_logger @@ -34,9 +36,10 @@ def get_prompt(self, name: str) -> Prompt | None: uri = self._normalize_to_uri(name) return self._prompts.get(uri) - def list_prompts(self, uri_paths: list[str] | None = None) -> list[Prompt]: + def list_prompts(self, uri_paths: list[AnyUrl] | None = None) -> list[Prompt]: """List all registered prompts, optionally filtered by URI paths.""" prompts = list(self._prompts.values()) - prompts = filter_by_uri_paths(prompts, uri_paths, lambda p: p.uri) + if uri_paths: + prompts = filter_by_uri_paths(prompts, uri_paths) logger.debug("Listing prompts", extra={"count": len(prompts), "uri_paths": uri_paths}) return prompts diff --git a/src/mcp/server/fastmcp/resources/resource_manager.py b/src/mcp/server/fastmcp/resources/resource_manager.py index c30219717..aaabf2a0f 100644 --- a/src/mcp/server/fastmcp/resources/resource_manager.py +++ b/src/mcp/server/fastmcp/resources/resource_manager.py @@ -87,14 +87,15 @@ async def get_resource(self, uri: AnyUrl | str) -> Resource | None: raise ValueError(f"Unknown resource: {uri}") - def list_resources(self, uri_paths: list[str] | None = None) -> list[Resource]: + def list_resources(self, uri_paths: list[AnyUrl] | None = None) -> list[Resource]: """List all registered resources, optionally filtered by URI paths.""" resources = list(self._resources.values()) - resources = filter_by_uri_paths(resources, uri_paths, lambda r: r.uri) + if uri_paths: + resources = filter_by_uri_paths(resources, uri_paths) logger.debug("Listing resources", extra={"count": len(resources), "uri_paths": uri_paths}) return resources - def list_templates(self, uri_paths: list[str] | None = None) -> list[ResourceTemplate]: + def list_templates(self, uri_paths: list[AnyUrl] | None = None) -> list[ResourceTemplate]: """List all registered templates, optionally filtered by URI paths.""" templates = list(self._templates.values()) if uri_paths: @@ -102,9 +103,10 @@ def list_templates(self, uri_paths: list[str] | None = None) -> list[ResourceTem for template in templates: for prefix in uri_paths: # Ensure prefix ends with / for proper path matching - if not prefix.endswith("/"): - prefix = prefix + "/" - if template.matches_prefix(prefix): + prefix_str = str(prefix) + if not prefix_str.endswith("/"): + prefix_str = prefix_str + "/" + if template.matches_prefix(prefix_str): filtered.append(template) break templates = filtered diff --git a/src/mcp/server/fastmcp/tools/base.py b/src/mcp/server/fastmcp/tools/base.py index 1751c367d..feb7def1d 100644 --- a/src/mcp/server/fastmcp/tools/base.py +++ b/src/mcp/server/fastmcp/tools/base.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING, Any, get_origin -from pydantic import BaseModel, Field +from pydantic import AnyUrl, BaseModel, Field from mcp.server.fastmcp.exceptions import ToolError from mcp.server.fastmcp.utilities.func_metadata import FuncMetadata, func_metadata @@ -22,7 +22,7 @@ class Tool(BaseModel): """Internal tool registration info.""" name: str = Field(description="Name of the tool") - uri: str = Field(description="URI of the tool") + uri: AnyUrl = Field(description="URI of the tool") title: str | None = Field(None, description="Human-readable title of the tool") description: str = Field(description="Description of what the tool does") fn: Callable[..., Any] = Field(exclude=True) @@ -37,7 +37,7 @@ class Tool(BaseModel): def __init__(self, **data: Any) -> None: """Initialize Tool, generating URI from name if not provided.""" if "uri" not in data and "name" in data: - data["uri"] = f"{TOOL_SCHEME}/{data['name']}" + data["uri"] = AnyUrl(f"{TOOL_SCHEME}/{data['name']}") super().__init__(**data) @cached_property diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index 6cd067731..4e30a93bb 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -1,7 +1,9 @@ from __future__ import annotations as _annotations from collections.abc import Callable -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, overload + +from pydantic import AnyUrl from mcp.server.fastmcp.exceptions import ToolError from mcp.server.fastmcp.tools.base import Tool @@ -39,15 +41,28 @@ def _normalize_to_uri(self, name_or_uri: str) -> str: """Convert name to URI if needed.""" return normalize_to_tool_uri(name_or_uri) - def get_tool(self, name: str) -> Tool | None: + @overload + def get_tool(self, name_or_uri: str) -> Tool | None: + """Get tool by name.""" + ... + + @overload + def get_tool(self, name_or_uri: AnyUrl) -> Tool | None: + """Get tool by URI.""" + ... + + def get_tool(self, name_or_uri: AnyUrl | str) -> Tool | None: """Get tool by name or URI.""" - uri = self._normalize_to_uri(name) + if isinstance(name_or_uri, AnyUrl): + return self._tools.get(str(name_or_uri)) + uri = self._normalize_to_uri(name_or_uri) return self._tools.get(uri) - def list_tools(self, uri_paths: list[str] | None = None) -> list[Tool]: + def list_tools(self, uri_paths: list[AnyUrl] | None = None) -> list[Tool]: """List all registered tools, optionally filtered by URI paths.""" tools = list(self._tools.values()) - tools = filter_by_uri_paths(tools, uri_paths, lambda t: t.uri) + if uri_paths: + tools = filter_by_uri_paths(tools, uri_paths) logger.debug("Listing tools", extra={"count": len(tools), "uri_paths": uri_paths}) return tools @@ -77,16 +92,38 @@ def add_tool( self._tools[str(tool.uri)] = tool return tool + @overload async def call_tool( self, - name: str, + name_or_uri: str, arguments: dict[str, Any], context: Context[ServerSessionT, LifespanContextT, RequestT] | None = None, convert_result: bool = False, ) -> Any: """Call a tool by name with arguments.""" - tool = self.get_tool(name) + ... + + @overload + async def call_tool( + self, + name_or_uri: AnyUrl, + arguments: dict[str, Any], + context: Context[ServerSessionT, LifespanContextT, RequestT] | None = None, + convert_result: bool = False, + ) -> Any: + """Call a tool by URI with arguments.""" + ... + + async def call_tool( + self, + name_or_uri: AnyUrl | str, + arguments: dict[str, Any], + context: Context[ServerSessionT, LifespanContextT, RequestT] | None = None, + convert_result: bool = False, + ) -> Any: + """Call a tool by name or URI with arguments.""" + tool = self.get_tool(name_or_uri) if not tool: - raise ToolError(f"Unknown tool: {name}") + raise ToolError(f"Unknown tool: {name_or_uri}") return await tool.run(arguments, context=context, convert_result=convert_result) diff --git a/src/mcp/server/fastmcp/uri_utils.py b/src/mcp/server/fastmcp/uri_utils.py index 69c018e9e..ab6931323 100644 --- a/src/mcp/server/fastmcp/uri_utils.py +++ b/src/mcp/server/fastmcp/uri_utils.py @@ -1,13 +1,13 @@ """Common URI utilities for FastMCP.""" -from collections.abc import Callable -from typing import TypeVar +from collections.abc import Sequence +from typing import Protocol, TypeVar, runtime_checkable from pydantic import AnyUrl from mcp.types import PROMPT_SCHEME, TOOL_SCHEME -T = TypeVar("T") +T = TypeVar("T", bound="HasUri") def normalize_to_uri(name_or_uri: str, scheme: str) -> str: @@ -35,34 +35,37 @@ def normalize_to_prompt_uri(name_or_uri: str) -> str: return normalize_to_uri(name_or_uri, PROMPT_SCHEME) -def filter_by_uri_paths( - items: list[T], uri_paths: list[str] | None, uri_getter: Callable[[T], AnyUrl | str] -) -> list[T]: +@runtime_checkable +class HasUri(Protocol): + """Protocol for objects that have a URI attribute.""" + + uri: AnyUrl + + +def filter_by_uri_paths(items: Sequence[T], uri_paths: Sequence[AnyUrl]) -> list[T]: """Filter items by multiple URI path prefixes. Args: - items: List of items to filter - uri_paths: Optional list of URI path prefixes to filter by. If None or empty, returns all items. - uri_getter: Function to extract URI from an item + items: List of items that have a 'uri' attribute + uri_paths: List of URI path prefixes to filter by. Returns: Filtered list of items matching any of the provided prefixes """ - if not uri_paths: - return items # Filter items where the URI matches any of the prefixes filtered: list[T] = [] for item in items: - uri = str(uri_getter(item)) + uri = str(item.uri) for prefix in uri_paths: - if uri.startswith(prefix): + prefix_str = str(prefix) + if uri.startswith(prefix_str): # If prefix ends with a separator, we already have a proper boundary - if prefix.endswith(("/", "?", "#")): + if prefix_str.endswith(("/", "?", "#")): filtered.append(item) break # Otherwise check if it's an exact match or if the next character is a separator - elif len(uri) == len(prefix) or uri[len(prefix)] in ("/", "?", "#"): + elif len(uri) == len(prefix_str) or uri[len(prefix_str)] in ("/", "?", "#"): filtered.append(item) break diff --git a/src/mcp/types.py b/src/mcp/types.py index cfc219d94..d28d38924 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -63,7 +63,7 @@ class Meta(BaseModel): class ListFilters(BaseModel): """Filters for list operations.""" - uri_paths: list[str] | None = None + uri_paths: list[AnyUrl] | None = None """Optional list of absolute URI path prefixes to filter results.""" diff --git a/tests/server/fastmcp/prompts/test_manager.py b/tests/server/fastmcp/prompts/test_manager.py index 1b1783418..210ecc85e 100644 --- a/tests/server/fastmcp/prompts/test_manager.py +++ b/tests/server/fastmcp/prompts/test_manager.py @@ -1,4 +1,5 @@ import pytest +from pydantic import AnyUrl from mcp.server.fastmcp.prompts.base import Prompt, TextContent, UserMessage from mcp.server.fastmcp.prompts.manager import PromptManager @@ -81,16 +82,16 @@ def question_age() -> str: # Create prompts with custom URIs hello_prompt = Prompt.from_function(greeting_hello) - hello_prompt.uri = f"{PROMPT_SCHEME}/greeting/hello" + hello_prompt.uri = AnyUrl(f"{PROMPT_SCHEME}/greeting/hello") goodbye_prompt = Prompt.from_function(greeting_goodbye) - goodbye_prompt.uri = f"{PROMPT_SCHEME}/greeting/goodbye" + goodbye_prompt.uri = AnyUrl(f"{PROMPT_SCHEME}/greeting/goodbye") name_prompt = Prompt.from_function(question_name) - name_prompt.uri = f"{PROMPT_SCHEME}/question/name" + name_prompt.uri = AnyUrl(f"{PROMPT_SCHEME}/question/name") age_prompt = Prompt.from_function(question_age) - age_prompt.uri = f"{PROMPT_SCHEME}/question/age" + age_prompt.uri = AnyUrl(f"{PROMPT_SCHEME}/question/age") # Add prompts directly to manager's internal storage manager._prompts = { @@ -105,40 +106,40 @@ def question_age() -> str: assert len(all_prompts) == 4 # Test uri_paths filtering - greeting prompts - greeting_prompts = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/"]) + greeting_prompts = manager.list_prompts(uri_paths=[AnyUrl(f"{PROMPT_SCHEME}/greeting/")]) assert len(greeting_prompts) == 2 assert all(str(p.uri).startswith(f"{PROMPT_SCHEME}/greeting/") for p in greeting_prompts) assert hello_prompt in greeting_prompts assert goodbye_prompt in greeting_prompts # Test uri_paths filtering - question prompts - question_prompts = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/question/"]) + question_prompts = manager.list_prompts(uri_paths=[AnyUrl(f"{PROMPT_SCHEME}/question/")]) assert len(question_prompts) == 2 assert all(str(p.uri).startswith(f"{PROMPT_SCHEME}/question/") for p in question_prompts) assert name_prompt in question_prompts assert age_prompt in question_prompts # Test exact URI match - hello_prompts = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/hello"]) + hello_prompts = manager.list_prompts(uri_paths=[AnyUrl(f"{PROMPT_SCHEME}/greeting/hello")]) assert len(hello_prompts) == 1 assert hello_prompts[0] == hello_prompt # Test partial prefix doesn't match - no_partial = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/h"]) + no_partial = manager.list_prompts(uri_paths=[AnyUrl(f"{PROMPT_SCHEME}/greeting/h")]) assert len(no_partial) == 0 # Won't match because next char is 'e' not a separator # Test no matches - no_matches = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/nonexistent"]) + no_matches = manager.list_prompts(uri_paths=[AnyUrl(f"{PROMPT_SCHEME}/nonexistent")]) assert len(no_matches) == 0 # Test with trailing slash - greeting_prompts_slash = manager.list_prompts(uri_paths=[f"{PROMPT_SCHEME}/greeting/"]) + greeting_prompts_slash = manager.list_prompts(uri_paths=[AnyUrl(f"{PROMPT_SCHEME}/greeting/")]) assert len(greeting_prompts_slash) == 2 assert greeting_prompts_slash == greeting_prompts # Test multiple uri_paths greeting_and_question = manager.list_prompts( - uri_paths=[f"{PROMPT_SCHEME}/greeting/", f"{PROMPT_SCHEME}/question/"] + uri_paths=[AnyUrl(f"{PROMPT_SCHEME}/greeting/"), AnyUrl(f"{PROMPT_SCHEME}/question/")] ) assert len(greeting_and_question) == 4 assert all(p in greeting_and_question for p in all_prompts) @@ -205,7 +206,7 @@ def custom_prompt() -> str: # Add prompt with custom URI custom = Prompt.from_function(custom_prompt) - custom.uri = f"{PROMPT_SCHEME}/custom/messages/welcome" + custom.uri = AnyUrl(f"{PROMPT_SCHEME}/custom/messages/welcome") manager._prompts[str(custom.uri)] = custom # Get by name @@ -241,7 +242,7 @@ def farewell(name: str) -> str: # Add prompt with custom URI farewell_prompt = Prompt.from_function(farewell) - farewell_prompt.uri = f"{PROMPT_SCHEME}/custom/farewell" + farewell_prompt.uri = AnyUrl(f"{PROMPT_SCHEME}/custom/farewell") manager._prompts[str(farewell_prompt.uri)] = farewell_prompt # Render by default URI diff --git a/tests/server/fastmcp/resources/test_resource_manager.py b/tests/server/fastmcp/resources/test_resource_manager.py index 438c6a7e2..c566d6196 100644 --- a/tests/server/fastmcp/resources/test_resource_manager.py +++ b/tests/server/fastmcp/resources/test_resource_manager.py @@ -166,22 +166,22 @@ def test_list_resources_with_prefix(self, temp_file: Path): manager.add_resource(resource3) # Test uri_paths filtering - data_resources = manager.list_resources(uri_paths=["file:///data/"]) + data_resources = manager.list_resources(uri_paths=[AnyUrl("file:///data/")]) assert len(data_resources) == 2 assert resource1 in data_resources assert resource2 in data_resources # More specific prefix - image_resources = manager.list_resources(uri_paths=["file:///data/images/"]) + image_resources = manager.list_resources(uri_paths=[AnyUrl("file:///data/images/")]) assert len(image_resources) == 1 assert resource1 in image_resources # No matches - no_matches = manager.list_resources(uri_paths=["file:///nonexistent/"]) + no_matches = manager.list_resources(uri_paths=[AnyUrl("file:///nonexistent/")]) assert len(no_matches) == 0 # Multiple uri_paths - multi_resources = manager.list_resources(uri_paths=["file:///data/", "file:///other/"]) + multi_resources = manager.list_resources(uri_paths=[AnyUrl("file:///data/"), AnyUrl("file:///other/")]) assert len(multi_resources) == 3 assert all(r in multi_resources for r in [resource1, resource2, resource3]) @@ -212,7 +212,7 @@ def product_func(product_id: str) -> str: assert len(all_templates) == 3 # Test uri_paths filtering - matches both user templates - user_templates = manager.list_templates(uri_paths=["http://api.com/users/"]) + user_templates = manager.list_templates(uri_paths=[AnyUrl("http://api.com/users/")]) assert len(user_templates) == 2 assert template1 in user_templates assert template2 in user_templates @@ -220,25 +220,27 @@ def product_func(product_id: str) -> str: # Test partial materialization - only matches post template # The template users/{user_id} generates "users/123" not "users/123/" # But users/{user_id}/posts/{post_id} can generate "users/123/posts/456" - user_123_templates = manager.list_templates(uri_paths=["http://api.com/users/123/"]) + user_123_templates = manager.list_templates(uri_paths=[AnyUrl("http://api.com/users/123/")]) assert len(user_123_templates) == 1 assert template2 in user_123_templates # users/{user_id}/posts/{post_id} matches # Without trailing slash, it gets added automatically so only posts template matches - user_123_no_slash = manager.list_templates(uri_paths=["http://api.com/users/123"]) + user_123_no_slash = manager.list_templates(uri_paths=[AnyUrl("http://api.com/users/123")]) assert len(user_123_no_slash) == 1 assert template2 in user_123_no_slash # Only posts template has path after users/123/ # Test product prefix - product_templates = manager.list_templates(uri_paths=["http://api.com/products/"]) + product_templates = manager.list_templates(uri_paths=[AnyUrl("http://api.com/products/")]) assert len(product_templates) == 1 assert template3 in product_templates # No matches - no_matches = manager.list_templates(uri_paths=["http://api.com/orders/"]) + no_matches = manager.list_templates(uri_paths=[AnyUrl("http://api.com/orders/")]) assert len(no_matches) == 0 # Multiple uri_paths - users_and_products = manager.list_templates(uri_paths=["http://api.com/users/", "http://api.com/products/"]) + users_and_products = manager.list_templates( + uri_paths=[AnyUrl("http://api.com/users/"), AnyUrl("http://api.com/products/")] + ) assert len(users_and_products) == 3 assert all(t in users_and_products for t in all_templates) diff --git a/tests/server/fastmcp/test_tool_manager.py b/tests/server/fastmcp/test_tool_manager.py index 29a0a35e4..2f04ea123 100644 --- a/tests/server/fastmcp/test_tool_manager.py +++ b/tests/server/fastmcp/test_tool_manager.py @@ -4,7 +4,7 @@ from typing import Any, TypedDict import pytest -from pydantic import BaseModel +from pydantic import AnyUrl, BaseModel from mcp.server.fastmcp import Context, FastMCP from mcp.server.fastmcp.exceptions import ToolError @@ -197,16 +197,16 @@ def string_upper(text: str) -> str: # Add tools with custom URIs math_add_tool = Tool.from_function(math_add) - math_add_tool.uri = f"{TOOL_SCHEME}/math/add" + math_add_tool.uri = AnyUrl(f"{TOOL_SCHEME}/math/add") math_multiply_tool = Tool.from_function(math_multiply) - math_multiply_tool.uri = f"{TOOL_SCHEME}/math/multiply" + math_multiply_tool.uri = AnyUrl(f"{TOOL_SCHEME}/math/multiply") string_concat_tool = Tool.from_function(string_concat) - string_concat_tool.uri = f"{TOOL_SCHEME}/string/concat" + string_concat_tool.uri = AnyUrl(f"{TOOL_SCHEME}/string/concat") string_upper_tool = Tool.from_function(string_upper) - string_upper_tool.uri = f"{TOOL_SCHEME}/string/upper" + string_upper_tool.uri = AnyUrl(f"{TOOL_SCHEME}/string/upper") manager._tools = { str(math_add_tool.uri): math_add_tool, @@ -220,39 +220,41 @@ def string_upper(text: str) -> str: assert len(all_tools) == 4 # Test uri_paths filtering - math tools - math_tools = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/"]) + math_tools = manager.list_tools(uri_paths=[AnyUrl(f"{TOOL_SCHEME}/math/")]) assert len(math_tools) == 2 assert all(str(t.uri).startswith(f"{TOOL_SCHEME}/math/") for t in math_tools) assert math_add_tool in math_tools assert math_multiply_tool in math_tools # Test uri_paths filtering - string tools - string_tools = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/string/"]) + string_tools = manager.list_tools(uri_paths=[AnyUrl(f"{TOOL_SCHEME}/string/")]) assert len(string_tools) == 2 assert all(str(t.uri).startswith(f"{TOOL_SCHEME}/string/") for t in string_tools) assert string_concat_tool in string_tools assert string_upper_tool in string_tools # Test exact URI match - add_tools = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/add"]) + add_tools = manager.list_tools(uri_paths=[AnyUrl(f"{TOOL_SCHEME}/math/add")]) assert len(add_tools) == 1 assert add_tools[0] == math_add_tool # Test partial prefix doesn't match - no_partial = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/a"]) + no_partial = manager.list_tools(uri_paths=[AnyUrl(f"{TOOL_SCHEME}/math/a")]) assert len(no_partial) == 0 # Won't match because next char is 'd' not a separator # Test no matches - no_matches = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/nonexistent"]) + no_matches = manager.list_tools(uri_paths=[AnyUrl(f"{TOOL_SCHEME}/nonexistent")]) assert len(no_matches) == 0 # Test with trailing slash - math_tools_slash = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/"]) + math_tools_slash = manager.list_tools(uri_paths=[AnyUrl(f"{TOOL_SCHEME}/math/")]) assert len(math_tools_slash) == 2 assert math_tools_slash == math_tools # Test multiple uri_paths - math_and_string = manager.list_tools(uri_paths=[f"{TOOL_SCHEME}/math/", f"{TOOL_SCHEME}/string/"]) + math_and_string = manager.list_tools( + uri_paths=[AnyUrl(f"{TOOL_SCHEME}/math/"), AnyUrl(f"{TOOL_SCHEME}/string/")] + ) assert len(math_and_string) == 4 assert all(t in math_and_string for t in all_tools) @@ -353,7 +355,7 @@ def math_multiply(a: int, b: int) -> int: # Add tool with custom URI multiply_tool = Tool.from_function(math_multiply) - multiply_tool.uri = f"{TOOL_SCHEME}/custom/math/multiply" + multiply_tool.uri = AnyUrl(f"{TOOL_SCHEME}/custom/math/multiply") manager._tools[str(multiply_tool.uri)] = multiply_tool # Call by default URI (TOOL_SCHEME/function_name) diff --git a/tests/server/fastmcp/test_uri_utils.py b/tests/server/fastmcp/test_uri_utils.py index 27329225a..9a8d90121 100644 --- a/tests/server/fastmcp/test_uri_utils.py +++ b/tests/server/fastmcp/test_uri_utils.py @@ -1,5 +1,7 @@ """Tests for URI utility functions.""" +from pydantic import AnyUrl + from mcp.server.fastmcp.uri_utils import ( filter_by_uri_paths, normalize_to_prompt_uri, @@ -79,117 +81,124 @@ def test_normalize_prompt_with_path(self): assert result == f"{PROMPT_SCHEME}/templates/greeting" +class MockUriItem: + """Mock item with a URI for testing.""" + + def __init__(self, uri: str): + self.uri = AnyUrl(uri) + + class TestFilterByUriPaths: """Test the URI paths filtering function.""" - def test_filter_no_paths(self): - """Test that no paths returns all items.""" - items = ["item1", "item2", "item3"] - result = filter_by_uri_paths(items, None, lambda x: x) - assert result == items - def test_filter_empty_paths(self): - """Test that empty paths list returns all items.""" - items = ["item1", "item2", "item3"] - result = filter_by_uri_paths(items, [], lambda x: x) - assert result == items + """Test that empty paths list returns empty result.""" + + class MockItem: + def __init__(self, uri: str): + self.uri = AnyUrl(uri) + + items = [MockItem("http://example.com/item1"), MockItem("http://example.com/item2")] + result = filter_by_uri_paths(items, []) + assert result == [] def test_filter_single_path(self): """Test filtering with a single path.""" - items = [f"{TOOL_SCHEME}/math/add", f"{TOOL_SCHEME}/math/subtract", f"{TOOL_SCHEME}/string/concat"] - result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math"], lambda x: x) + items = [ + MockUriItem(f"{TOOL_SCHEME}/math/add"), + MockUriItem(f"{TOOL_SCHEME}/math/subtract"), + MockUriItem(f"{TOOL_SCHEME}/string/concat"), + ] + result = filter_by_uri_paths(items, [AnyUrl(f"{TOOL_SCHEME}/math")]) assert len(result) == 2 - assert f"{TOOL_SCHEME}/math/add" in result - assert f"{TOOL_SCHEME}/math/subtract" in result + assert any(str(item.uri) == f"{TOOL_SCHEME}/math/add" for item in result) + assert any(str(item.uri) == f"{TOOL_SCHEME}/math/subtract" for item in result) def test_filter_multiple_paths(self): """Test filtering with multiple paths.""" items = [ - f"{TOOL_SCHEME}/math/add", - f"{TOOL_SCHEME}/math/subtract", - f"{TOOL_SCHEME}/string/concat", - f"{PROMPT_SCHEME}/greet/hello", + MockUriItem(f"{TOOL_SCHEME}/math/add"), + MockUriItem(f"{TOOL_SCHEME}/math/subtract"), + MockUriItem(f"{TOOL_SCHEME}/string/concat"), + MockUriItem(f"{PROMPT_SCHEME}/greet/hello"), ] - result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math", f"{PROMPT_SCHEME}/greet"], lambda x: x) + result = filter_by_uri_paths(items, [AnyUrl(f"{TOOL_SCHEME}/math"), AnyUrl(f"{PROMPT_SCHEME}/greet")]) assert len(result) == 3 - assert f"{TOOL_SCHEME}/math/add" in result - assert f"{TOOL_SCHEME}/math/subtract" in result - assert f"{PROMPT_SCHEME}/greet/hello" in result - assert f"{TOOL_SCHEME}/string/concat" not in result + assert any(str(item.uri) == f"{TOOL_SCHEME}/math/add" for item in result) + assert any(str(item.uri) == f"{TOOL_SCHEME}/math/subtract" for item in result) + assert any(str(item.uri) == f"{PROMPT_SCHEME}/greet/hello" for item in result) + assert not any(str(item.uri) == f"{TOOL_SCHEME}/string/concat" for item in result) def test_filter_paths_without_slash(self): """Test that paths without trailing slash only match at boundaries.""" items = [ - f"{TOOL_SCHEME}/math/add", - f"{TOOL_SCHEME}/math/subtract", - f"{TOOL_SCHEME}/string/concat", - f"{TOOL_SCHEME}/mathematic", + MockUriItem(f"{TOOL_SCHEME}/math/add"), + MockUriItem(f"{TOOL_SCHEME}/math/subtract"), + MockUriItem(f"{TOOL_SCHEME}/string/concat"), + MockUriItem(f"{TOOL_SCHEME}/mathematic"), ] - result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math", f"{TOOL_SCHEME}/string"], lambda x: x) + result = filter_by_uri_paths(items, [AnyUrl(f"{TOOL_SCHEME}/math"), AnyUrl(f"{TOOL_SCHEME}/string")]) assert len(result) == 3 - assert f"{TOOL_SCHEME}/math/add" in result - assert f"{TOOL_SCHEME}/math/subtract" in result - assert f"{TOOL_SCHEME}/string/concat" in result - assert f"{TOOL_SCHEME}/mathematic" not in result + assert any(str(item.uri) == f"{TOOL_SCHEME}/math/add" for item in result) + assert any(str(item.uri) == f"{TOOL_SCHEME}/math/subtract" for item in result) + assert any(str(item.uri) == f"{TOOL_SCHEME}/string/concat" for item in result) + assert not any(str(item.uri) == f"{TOOL_SCHEME}/mathematic" for item in result) def test_filter_with_trailing_slashes(self): """Test filtering when paths have trailing slashes.""" items = [ - f"{PROMPT_SCHEME}/greet/hello", - f"{PROMPT_SCHEME}/greet/goodbye", - f"{PROMPT_SCHEME}/chat/start", + MockUriItem(f"{PROMPT_SCHEME}/greet/hello"), + MockUriItem(f"{PROMPT_SCHEME}/greet/goodbye"), + MockUriItem(f"{PROMPT_SCHEME}/chat/start"), ] - result = filter_by_uri_paths(items, [f"{PROMPT_SCHEME}/greet/", f"{PROMPT_SCHEME}/chat/"], lambda x: x) + result = filter_by_uri_paths(items, [AnyUrl(f"{PROMPT_SCHEME}/greet/"), AnyUrl(f"{PROMPT_SCHEME}/chat/")]) assert len(result) == 3 - assert all(item in result for item in items) def test_filter_overlapping_paths(self): """Test filtering with overlapping paths.""" items = [ - f"{TOOL_SCHEME}/math", - f"{TOOL_SCHEME}/math/add", - f"{TOOL_SCHEME}/math/advanced/multiply", + MockUriItem(f"{TOOL_SCHEME}/math"), + MockUriItem(f"{TOOL_SCHEME}/math/add"), + MockUriItem(f"{TOOL_SCHEME}/math/advanced/multiply"), ] - result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math", f"{TOOL_SCHEME}/math/advanced"], lambda x: x) + result = filter_by_uri_paths(items, [AnyUrl(f"{TOOL_SCHEME}/math"), AnyUrl(f"{TOOL_SCHEME}/math/advanced")]) assert len(result) == 3 # All items match - assert all(item in result for item in items) def test_filter_no_matches(self): """Test filtering when no items match any path.""" - items = [f"{TOOL_SCHEME}/math/add", f"{TOOL_SCHEME}/math/subtract"] - result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/string", f"{PROMPT_SCHEME}/greet"], lambda x: x) + items = [MockUriItem(f"{TOOL_SCHEME}/math/add"), MockUriItem(f"{TOOL_SCHEME}/math/subtract")] + result = filter_by_uri_paths(items, [AnyUrl(f"{TOOL_SCHEME}/string"), AnyUrl(f"{PROMPT_SCHEME}/greet")]) assert result == [] def test_filter_with_objects(self): - """Test filtering objects using a URI getter function.""" - - class MockResource: - def __init__(self, uri): - self.uri = uri - + """Test filtering objects with URI attributes.""" resources = [ - MockResource(f"{TOOL_SCHEME}/math/add"), - MockResource(f"{TOOL_SCHEME}/string/concat"), - MockResource(f"{PROMPT_SCHEME}/greet/hello"), + MockUriItem(f"{TOOL_SCHEME}/math/add"), + MockUriItem(f"{TOOL_SCHEME}/string/concat"), + MockUriItem(f"{PROMPT_SCHEME}/greet/hello"), ] - result = filter_by_uri_paths(resources, [f"{TOOL_SCHEME}/math", f"{PROMPT_SCHEME}/greet"], lambda r: r.uri) + result = filter_by_uri_paths(resources, [AnyUrl(f"{TOOL_SCHEME}/math"), AnyUrl(f"{PROMPT_SCHEME}/greet")]) assert len(result) == 2 - assert result[0].uri == f"{TOOL_SCHEME}/math/add" - assert result[1].uri == f"{PROMPT_SCHEME}/greet/hello" + assert str(result[0].uri) == f"{TOOL_SCHEME}/math/add" + assert str(result[1].uri) == f"{PROMPT_SCHEME}/greet/hello" def test_filter_case_sensitive(self): """Test that filtering is case sensitive.""" - items = [f"{TOOL_SCHEME}/Math/add", f"{TOOL_SCHEME}/math/add"] - result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/math"], lambda x: x) + items = [MockUriItem(f"{TOOL_SCHEME}/Math/add"), MockUriItem(f"{TOOL_SCHEME}/math/add")] + result = filter_by_uri_paths(items, [AnyUrl(f"{TOOL_SCHEME}/math")]) assert len(result) == 1 - assert f"{TOOL_SCHEME}/math/add" in result + assert any(str(item.uri) == f"{TOOL_SCHEME}/math/add" for item in result) def test_filter_exact_path_match(self): """Test that exact path matches work correctly.""" - items = [f"{TOOL_SCHEME}/test", f"{TOOL_SCHEME}/test/sub", f"{TOOL_SCHEME}/testing"] - result = filter_by_uri_paths(items, [f"{TOOL_SCHEME}/test"], lambda x: x) + items = [ + MockUriItem(f"{TOOL_SCHEME}/test"), + MockUriItem(f"{TOOL_SCHEME}/test/sub"), + MockUriItem(f"{TOOL_SCHEME}/testing"), + ] + result = filter_by_uri_paths(items, [AnyUrl(f"{TOOL_SCHEME}/test")]) assert len(result) == 2 - assert f"{TOOL_SCHEME}/test" in result - assert f"{TOOL_SCHEME}/test/sub" in result - assert f"{TOOL_SCHEME}/testing" not in result + assert any(str(item.uri) == f"{TOOL_SCHEME}/test" for item in result) + assert any(str(item.uri) == f"{TOOL_SCHEME}/test/sub" for item in result) + assert not any(str(item.uri) == f"{TOOL_SCHEME}/testing" for item in result) diff --git a/types_protocol_changes.md b/types_protocol_changes.md index 18bba3574..2a135e67e 100644 --- a/types_protocol_changes.md +++ b/types_protocol_changes.md @@ -3,6 +3,7 @@ ## URI Standardization ### Added URI schemes + ```python MCP_SCHEME = "mcp" TOOL_SCHEME = "mcp://tools" @@ -12,6 +13,7 @@ PROMPT_SCHEME = "mcp://prompts" ## Request/Response Changes ### Renamed pagination to list-based naming + ```python # Before class PaginatedRequestParams(RequestParams): @@ -32,6 +34,7 @@ class ListResult(Result) ## Tool Protocol Changes ### Tool now includes URI + ```python class Tool(BaseMetadata): uri: AnyUrl | None = None # NEW: auto-generated as mcp://tools/{name} @@ -42,6 +45,7 @@ class Tool(BaseMetadata): ## Prompt Protocol Changes ### Prompt now includes URI + ```python class Prompt(BaseMetadata): uri: AnyUrl | None = None # NEW: auto-generated as mcp://prompts/{name} @@ -52,6 +56,7 @@ class Prompt(BaseMetadata): ## Resource Validation ### Resources cannot use tool/prompt URI schemes + ```python @model_validator(mode="after") def validate_uri_scheme(self) -> "Resource": @@ -61,7 +66,8 @@ def validate_uri_scheme(self) -> "Resource": ## List Methods Update All list requests now support prefix filtering: + - `ListResourcesRequest` -- `ListToolsRequest` +- `ListToolsRequest` - `ListPromptsRequest` -- `ListResourceTemplatesRequest` \ No newline at end of file +- `ListResourceTemplatesRequest` From d4ead25fb4aa7d21c7535d0353ec53d520edc490 Mon Sep 17 00:00:00 2001 From: Tapan Chugh Date: Sun, 3 Aug 2025 18:09:47 -0700 Subject: [PATCH 15/15] Add example + minor fixes + add tests --- .../servers/hierarchical_organization.py | 182 ++++++++++++++++++ src/mcp/server/fastmcp/prompts/base.py | 4 +- src/mcp/server/fastmcp/prompts/manager.py | 11 ++ src/mcp/server/fastmcp/server.py | 15 +- src/mcp/server/fastmcp/tools/base.py | 4 +- src/mcp/server/fastmcp/tools/tool_manager.py | 15 +- src/mcp/types.py | 13 +- tests/server/fastmcp/prompts/test_manager.py | 128 +++++++++++- tests/server/fastmcp/test_tool_manager.py | 111 ++++++++++- types_protocol_changes.md | 73 ------- 10 files changed, 467 insertions(+), 89 deletions(-) create mode 100644 examples/snippets/servers/hierarchical_organization.py delete mode 100644 types_protocol_changes.md diff --git a/examples/snippets/servers/hierarchical_organization.py b/examples/snippets/servers/hierarchical_organization.py new file mode 100644 index 000000000..2e6cd49c7 --- /dev/null +++ b/examples/snippets/servers/hierarchical_organization.py @@ -0,0 +1,182 @@ +"""Example demonstrating hierarchical organization of tools, prompts, and resources using custom URIs. + +This example shows how to: +1. Register tools, prompts, and resources with hierarchical URIs +2. Create group discovery resources at well-known URIs +3. Filter items by URI paths for better organization +""" + +import json +from typing import cast + +from pydantic import AnyUrl + +from mcp.server.fastmcp import FastMCP +from mcp.types import ListFilters, TextContent, TextResourceContents + +# Create FastMCP server instance +mcp = FastMCP("hierarchical-example") + + +# Group discovery resources +@mcp.resource("mcp://groups/tools") +def get_tool_groups() -> str: + """Discover available tool groups.""" + return json.dumps( + { + "groups": [ + {"name": "math", "description": "Mathematical operations", "uri_paths": ["mcp://tools/math/"]}, + {"name": "string", "description": "String manipulation", "uri_paths": ["mcp://tools/string/"]}, + ] + }, + indent=2, + ) + + +@mcp.resource("mcp://groups/prompts") +def get_prompt_groups() -> str: + """Discover available prompt groups.""" + return json.dumps( + { + "groups": [ + {"name": "greetings", "description": "Greeting prompts", "uri_paths": ["mcp://prompts/greetings/"]}, + { + "name": "instructions", + "description": "Instructional prompts", + "uri_paths": ["mcp://prompts/instructions/"], + }, + ] + }, + indent=2, + ) + + +# Math tools organized under mcp://tools/math/ +@mcp.tool(uri="mcp://tools/math/add") +def add(a: float, b: float) -> float: + """Add two numbers.""" + return a + b + + +@mcp.tool(uri="mcp://tools/math/multiply") +def multiply(a: float, b: float) -> float: + """Multiply two numbers.""" + return a * b + + +# String tools organized under mcp://tools/string/ +@mcp.tool(uri="mcp://tools/string/reverse") +def reverse(text: str) -> str: + """Reverse a string.""" + return text[::-1] + + +@mcp.tool(uri="mcp://tools/string/upper") +def upper(text: str) -> str: + """Convert to uppercase.""" + return text.upper() + + +# Greeting prompts organized under mcp://prompts/greetings/ +@mcp.prompt(uri="mcp://prompts/greetings/hello") +def hello_prompt(name: str) -> str: + """Generate a hello greeting.""" + return f"Hello, {name}! How can I help you today?" + + +@mcp.prompt(uri="mcp://prompts/greetings/goodbye") +def goodbye_prompt(name: str) -> str: + """Generate a goodbye message.""" + return f"Goodbye, {name}! Have a great day!" + + +# Instruction prompts organized under mcp://prompts/instructions/ +@mcp.prompt(uri="mcp://prompts/instructions/setup") +def setup_prompt(tool: str) -> str: + """Generate setup instructions for a tool.""" + return ( + f"To set up {tool}, follow these steps:\n" + "1. Install the required dependencies\n" + "2. Configure the settings\n" + "3. Run the initialization script\n" + "4. Verify the installation" + ) + + +@mcp.prompt(uri="mcp://prompts/instructions/debug") +def debug_prompt(error: str) -> str: + """Generate debugging instructions for an error.""" + return ( + f"To debug '{error}':\n" + "1. Check the error logs\n" + "2. Verify input parameters\n" + "3. Enable verbose logging\n" + "4. Isolate the issue with minimal reproduction" + ) + + +if __name__ == "__main__": + # Example of testing the hierarchical organization + import asyncio + + from mcp.shared.memory import create_connected_server_and_client_session + + async def test_hierarchy(): + """Test the hierarchical organization.""" + async with create_connected_server_and_client_session(mcp._mcp_server) as client: + # 1. Discover tool groups and list tools in each group + print("\n=== Discovering Tool Groups ===") + result = await client.read_resource(uri=AnyUrl("mcp://groups/tools")) + tool_groups = json.loads(cast(TextResourceContents, result.contents[0]).text) + + for group in tool_groups["groups"]: + print(f"\n--- {group['name'].upper()} Tools ({group['description']}) ---") + # Use the URI paths from the group definition + group_tools = await client.list_tools( + filters=ListFilters(uri_paths=[AnyUrl(uri) for uri in group["uri_paths"]]) + ) + for tool in group_tools.tools: + print(f" - {tool.name}: {tool.description}") + + # 2. Call tools by name (still works!) + print("\n=== Calling Tools by Name ===") + result = await client.call_tool("add", {"a": 10, "b": 5}) + print(f"add(10, 5) = {cast(TextContent, result.content[0]).text}") + + result = await client.call_tool("reverse", {"text": "Hello"}) + print(f"reverse('Hello') = {cast(TextContent, result.content[0]).text}") + + # 3. Call tools by URI + print("\n=== Calling Tools by URI ===") + result = await client.call_tool("mcp://tools/math/multiply", {"a": 7, "b": 8}) + print( + f"Call mcp://tools/math/multiply with {{'a': 7, 'b': 8}} = {cast(TextContent, result.content[0]).text}" + ) + + result = await client.call_tool("mcp://tools/string/upper", {"text": "hello world"}) + print( + f"Call mcp://tools/string/upper with {{'text': 'hello world'}} = " + f"{cast(TextContent, result.content[0]).text}" + ) + + # 4. Discover prompt groups and list prompts in each group + print("\n=== Discovering Prompt Groups ===") + result = await client.read_resource(uri=AnyUrl("mcp://groups/prompts")) + prompt_groups = json.loads(cast(TextResourceContents, result.contents[0]).text) + + for group in prompt_groups["groups"]: + print(f"\n--- {group['name'].upper()} Prompts ({group['description']}) ---") + # Use the URI paths from the group definition + group_prompts = await client.list_prompts( + filters=ListFilters(uri_paths=[AnyUrl(uri) for uri in group["uri_paths"]]) + ) + for prompt in group_prompts.prompts: + print(f" - {prompt.name}: {prompt.description}") + + # 5. Use a prompt + print("\n=== Using a Prompt ===") + result = await client.get_prompt("hello_prompt", {"name": "Alice"}) + print(f"Prompt result: {cast(TextContent, result.messages[0].content).text}") + + # Run the test + asyncio.run(test_hierarchy()) diff --git a/src/mcp/server/fastmcp/prompts/base.py b/src/mcp/server/fastmcp/prompts/base.py index 4a19c0ed0..52d331b78 100644 --- a/src/mcp/server/fastmcp/prompts/base.py +++ b/src/mcp/server/fastmcp/prompts/base.py @@ -66,7 +66,7 @@ class Prompt(BaseModel): def __init__(self, **data: Any) -> None: """Initialize Prompt, generating URI from name if not provided.""" - if "uri" not in data and "name" in data: + if not data.get("uri", None): data["uri"] = AnyUrl(f"{PROMPT_SCHEME}/{data['name']}") super().__init__(**data) @@ -75,6 +75,7 @@ def from_function( cls, fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, + uri: str | AnyUrl | None = None, title: str | None = None, description: str | None = None, ) -> "Prompt": @@ -112,6 +113,7 @@ def from_function( return cls( name=func_name, + uri=uri, title=title, description=description or fn.__doc__ or "", arguments=arguments, diff --git a/src/mcp/server/fastmcp/prompts/manager.py b/src/mcp/server/fastmcp/prompts/manager.py index 8a74a63a9..b804cd0cd 100644 --- a/src/mcp/server/fastmcp/prompts/manager.py +++ b/src/mcp/server/fastmcp/prompts/manager.py @@ -36,6 +36,17 @@ def get_prompt(self, name_or_uri: AnyUrl | str) -> Prompt | None: """Get prompt by name or URI.""" if isinstance(name_or_uri, AnyUrl): return self._prompts.get(str(name_or_uri)) + + # Try as a direct URI first + if name_or_uri in self._prompts: + return self._prompts[name_or_uri] + + # Try to find a prompt by name + for prompt in self._prompts.values(): + if prompt.name == name_or_uri: + return prompt + + # Finally try normalizing to URI uri = self._normalize_to_uri(name_or_uri) return self._prompts.get(uri) diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 7e4dcb61a..f442c96d7 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -355,6 +355,7 @@ def add_tool( self, fn: AnyFunction, name: str | None = None, + uri: str | AnyUrl | None = None, title: str | None = None, description: str | None = None, annotations: ToolAnnotations | None = None, @@ -368,6 +369,7 @@ def add_tool( Args: fn: The function to register as a tool name: Optional name for the tool (defaults to function name) + uri: Optional URI for the tool (defaults to {TOOL_SCHEME}/{{name}}) title: Optional human-readable title for the tool description: Optional description of what the tool does annotations: Optional ToolAnnotations providing additional tool information @@ -379,6 +381,7 @@ def add_tool( self._tool_manager.add_tool( fn, name=name, + uri=uri, title=title, description=description, annotations=annotations, @@ -388,6 +391,7 @@ def add_tool( def tool( self, name: str | None = None, + uri: str | AnyUrl | None = None, title: str | None = None, description: str | None = None, annotations: ToolAnnotations | None = None, @@ -401,6 +405,7 @@ def tool( Args: name: Optional name for the tool (defaults to function name) + uri: Optional URI for the tool (defaults to {TOOL_SCHEME}/{{name}}) title: Optional human-readable title for the tool description: Optional description of what the tool does annotations: Optional ToolAnnotations providing additional tool information @@ -434,6 +439,7 @@ def decorator(fn: AnyFunction) -> AnyFunction: self.add_tool( fn, name=name, + uri=uri, title=title, description=description, annotations=annotations, @@ -570,12 +576,17 @@ def add_prompt(self, prompt: Prompt) -> None: self._prompt_manager.add_prompt(prompt) def prompt( - self, name: str | None = None, title: str | None = None, description: str | None = None + self, + name: str | None = None, + uri: str | AnyUrl | None = None, + title: str | None = None, + description: str | None = None, ) -> Callable[[AnyFunction], AnyFunction]: """Decorator to register a prompt. Args: name: Optional name for the prompt (defaults to function name) + uri: Optional URI for the prompt (defaults to {PROMPT_SCHEME}/{{name}}) title: Optional human-readable title for the prompt description: Optional description of what the prompt does @@ -614,7 +625,7 @@ async def analyze_file(path: str) -> list[Message]: ) def decorator(func: AnyFunction) -> AnyFunction: - prompt = Prompt.from_function(func, name=name, title=title, description=description) + prompt = Prompt.from_function(func, name=name, uri=uri, title=title, description=description) self.add_prompt(prompt) return func diff --git a/src/mcp/server/fastmcp/tools/base.py b/src/mcp/server/fastmcp/tools/base.py index feb7def1d..79d539d2b 100644 --- a/src/mcp/server/fastmcp/tools/base.py +++ b/src/mcp/server/fastmcp/tools/base.py @@ -36,7 +36,7 @@ class Tool(BaseModel): def __init__(self, **data: Any) -> None: """Initialize Tool, generating URI from name if not provided.""" - if "uri" not in data and "name" in data: + if not data.get("uri", None): data["uri"] = AnyUrl(f"{TOOL_SCHEME}/{data['name']}") super().__init__(**data) @@ -49,6 +49,7 @@ def from_function( cls, fn: Callable[..., Any], name: str | None = None, + uri: str | AnyUrl | None = None, title: str | None = None, description: str | None = None, context_kwarg: str | None = None, @@ -85,6 +86,7 @@ def from_function( return cls( fn=fn, name=func_name, + uri=uri, title=title, description=func_doc, parameters=parameters, diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index 4e30a93bb..8efa5acd8 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -31,7 +31,7 @@ def __init__( self._tools: dict[str, Tool] = {} if tools is not None: for tool in tools: - if warn_on_duplicate_tools and tool.uri in self._tools: + if warn_on_duplicate_tools and str(tool.uri) in self._tools: logger.warning(f"Tool already exists: {tool.uri}") self._tools[str(tool.uri)] = tool @@ -55,6 +55,17 @@ def get_tool(self, name_or_uri: AnyUrl | str) -> Tool | None: """Get tool by name or URI.""" if isinstance(name_or_uri, AnyUrl): return self._tools.get(str(name_or_uri)) + + # Try as a direct URI first + if name_or_uri in self._tools: + return self._tools[name_or_uri] + + # Try to find a tool by name + for tool in self._tools.values(): + if tool.name == name_or_uri: + return tool + + # Finally try normalizing to URI uri = self._normalize_to_uri(name_or_uri) return self._tools.get(uri) @@ -70,6 +81,7 @@ def add_tool( self, fn: Callable[..., Any], name: str | None = None, + uri: str | AnyUrl | None = None, title: str | None = None, description: str | None = None, annotations: ToolAnnotations | None = None, @@ -79,6 +91,7 @@ def add_tool( tool = Tool.from_function( fn, name=name, + uri=uri, title=title, description=description, annotations=annotations, diff --git a/src/mcp/types.py b/src/mcp/types.py index d28d38924..d63d22244 100644 --- a/src/mcp/types.py +++ b/src/mcp/types.py @@ -9,6 +9,15 @@ MCP_SCHEME = "mcp" TOOL_SCHEME = f"{MCP_SCHEME}://tools" PROMPT_SCHEME = f"{MCP_SCHEME}://prompts" +RESOURCE_SCHEME = f"{MCP_SCHEME}://resources" +GROUP_SCHEME = f"{MCP_SCHEME}://groups" + +# Well-known MCP group URIs +WELL_KNOWN_GROUP_URIS = { + f"{GROUP_SCHEME}/tools", + f"{GROUP_SCHEME}/prompts", + f"{GROUP_SCHEME}/resources", +} """ Model Context Protocol bindings for Python @@ -447,9 +456,9 @@ class Resource(BaseMetadata): @model_validator(mode="after") def validate_uri_scheme(self) -> "Resource": - """Ensure resource URI doesn't use reserved MCP scheme.""" + """Ensure resource URI doesn't use reserved MCP scheme, except for well-known group URIs.""" uri_str = str(self.uri) - if uri_str.startswith(f"{MCP_SCHEME}://"): + if uri_str.startswith(f"{MCP_SCHEME}://") and uri_str not in WELL_KNOWN_GROUP_URIS: raise ValueError(f"Resource URI cannot use reserved MCP scheme '{MCP_SCHEME}://', got: {self.uri}") return self diff --git a/tests/server/fastmcp/prompts/test_manager.py b/tests/server/fastmcp/prompts/test_manager.py index 210ecc85e..9c55afaf7 100644 --- a/tests/server/fastmcp/prompts/test_manager.py +++ b/tests/server/fastmcp/prompts/test_manager.py @@ -205,9 +205,8 @@ def custom_prompt() -> str: manager.add_prompt(Prompt.from_function(greeting)) # Add prompt with custom URI - custom = Prompt.from_function(custom_prompt) - custom.uri = AnyUrl(f"{PROMPT_SCHEME}/custom/messages/welcome") - manager._prompts[str(custom.uri)] = custom + custom = Prompt.from_function(custom_prompt, uri=f"{PROMPT_SCHEME}/custom/messages/welcome") + manager.add_prompt(custom) # Get by name prompt = manager.get_prompt("greeting") @@ -225,6 +224,11 @@ def custom_prompt() -> str: assert custom_by_uri is not None assert custom_by_uri == custom + # Custom URI prompt should also work with name + custom_by_name = manager.get_prompt("custom_prompt") + assert custom_by_name is not None + assert custom_by_name == custom + @pytest.mark.anyio async def test_render_prompt_by_uri(self): """Test rendering prompts by their URI.""" @@ -241,9 +245,8 @@ def farewell(name: str) -> str: manager.add_prompt(Prompt.from_function(welcome)) # Add prompt with custom URI - farewell_prompt = Prompt.from_function(farewell) - farewell_prompt.uri = AnyUrl(f"{PROMPT_SCHEME}/custom/farewell") - manager._prompts[str(farewell_prompt.uri)] = farewell_prompt + farewell_prompt = Prompt.from_function(farewell, uri=f"{PROMPT_SCHEME}/custom/farewell") + manager.add_prompt(farewell_prompt) # Render by default URI messages = await manager.render_prompt(f"{PROMPT_SCHEME}/welcome", arguments={"name": "Alice"}) @@ -256,3 +259,116 @@ def farewell(name: str) -> str: # Should still work with name messages = await manager.render_prompt("welcome", arguments={"name": "Charlie"}) assert messages == [UserMessage(content=TextContent(type="text", text="Welcome, Charlie!"))] + + # Custom URI prompt should also work with name + messages = await manager.render_prompt("farewell", arguments={"name": "David"}) + assert messages == [UserMessage(content=TextContent(type="text", text="Goodbye, David!"))] + + def test_add_prompt_with_custom_uri(self): + """Test adding prompts with custom URI parameter.""" + + def greeting(name: str) -> str: + return f"Hello, {name}!" + + def question(topic: str) -> str: + return f"What do you think about {topic}?" + + manager = PromptManager() + + # Add prompt with custom hierarchical URI + prompt1 = Prompt.from_function(greeting, uri="mcp://prompts/greetings/hello") + added1 = manager.add_prompt(prompt1) + assert added1.name == "greeting" + assert str(added1.uri) == "mcp://prompts/greetings/hello" + + # Add prompt with AnyUrl + prompt2 = Prompt.from_function(question, uri=AnyUrl("mcp://prompts/questions/general")) + added2 = manager.add_prompt(prompt2) + assert added2.name == "question" + assert str(added2.uri) == "mcp://prompts/questions/general" + + # Verify prompts are stored by URI + assert str(prompt1.uri) in manager._prompts + assert str(prompt2.uri) in manager._prompts + + def test_get_prompt_by_name_with_custom_uri(self): + """Test getting prompts by name when they have custom URIs.""" + + def welcome(name: str) -> str: + return f"Welcome, {name}!" + + def goodbye(name: str) -> str: + return f"Goodbye, {name}!" + + manager = PromptManager() + + # Add prompts with custom URIs + welcome_prompt = Prompt.from_function(welcome, uri="mcp://prompts/greetings/welcome") + goodbye_prompt = Prompt.from_function(goodbye, uri="mcp://prompts/greetings/goodbye") + + manager.add_prompt(welcome_prompt) + manager.add_prompt(goodbye_prompt) + + # Should be able to get by name + prompt_by_name = manager.get_prompt("welcome") + assert prompt_by_name is not None + assert prompt_by_name == welcome_prompt + + # Should also work for the second prompt + prompt_by_name2 = manager.get_prompt("goodbye") + assert prompt_by_name2 is not None + assert prompt_by_name2 == goodbye_prompt + + # Should also be able to get by URI + prompt_by_uri = manager.get_prompt("mcp://prompts/greetings/welcome") + assert prompt_by_uri == welcome_prompt + + # Get by AnyUrl + prompt_by_anyurl = manager.get_prompt(AnyUrl("mcp://prompts/greetings/goodbye")) + assert prompt_by_anyurl == goodbye_prompt + + @pytest.mark.anyio + async def test_prompt_name_lookup_with_hierarchical_uri(self): + """Test name lookup works correctly with hierarchical URIs.""" + + def hello(name: str) -> str: + return f"Hello, {name}!" + + def askname() -> str: + return "What is your name?" + + def confirm(action: str) -> str: + return f"Are you sure you want to {action}?" + + manager = PromptManager() + + # Add prompts with hierarchical URIs + hello_prompt = Prompt.from_function(hello, uri="mcp://prompts/greetings/hello") + askname_prompt = Prompt.from_function(askname, uri="mcp://prompts/questions/askname") + confirm_prompt = Prompt.from_function(confirm, uri="mcp://prompts/confirmations/confirm") + + manager.add_prompt(hello_prompt) + manager.add_prompt(askname_prompt) + manager.add_prompt(confirm_prompt) + + # Test rendering by name + messages = await manager.render_prompt("hello", {"name": "Alice"}) + assert messages == [UserMessage(content=TextContent(type="text", text="Hello, Alice!"))] + + messages = await manager.render_prompt("askname") + assert messages == [UserMessage(content=TextContent(type="text", text="What is your name?"))] + + messages = await manager.render_prompt("confirm", {"action": "delete"}) + assert messages == [UserMessage(content=TextContent(type="text", text="Are you sure you want to delete?"))] + + # Test rendering by full URI + messages = await manager.render_prompt("mcp://prompts/greetings/hello", {"name": "Bob"}) + assert messages == [UserMessage(content=TextContent(type="text", text="Hello, Bob!"))] + + messages = await manager.render_prompt(AnyUrl("mcp://prompts/questions/askname")) + assert messages == [UserMessage(content=TextContent(type="text", text="What is your name?"))] + + # Verify that the standard normalization doesn't work + # (since prompts are at custom URIs, not standard ones) + prompt = manager.get_prompt(f"{PROMPT_SCHEME}/hello") + assert prompt is None # Should not find it at the standard URI diff --git a/tests/server/fastmcp/test_tool_manager.py b/tests/server/fastmcp/test_tool_manager.py index 2f04ea123..1973ed7bf 100644 --- a/tests/server/fastmcp/test_tool_manager.py +++ b/tests/server/fastmcp/test_tool_manager.py @@ -258,6 +258,109 @@ def string_upper(text: str) -> str: assert len(math_and_string) == 4 assert all(t in math_and_string for t in all_tools) + def test_add_tool_with_custom_uri(self): + """Test adding tools with custom URI parameter.""" + + def math_add(a: int, b: int) -> int: + return a + b + + def string_concat(a: str, b: str) -> str: + return a + b + + manager = ToolManager() + + # Add tool with custom hierarchical URI + tool1 = manager.add_tool(math_add, uri="mcp://tools/math/add") + assert tool1.name == "math_add" + assert str(tool1.uri) == "mcp://tools/math/add" + + # Add tool with AnyUrl + tool2 = manager.add_tool(string_concat, uri=AnyUrl("mcp://tools/string/concat")) + assert tool2.name == "string_concat" + assert str(tool2.uri) == "mcp://tools/string/concat" + + # Verify tools are stored by URI + assert str(tool1.uri) in manager._tools + assert str(tool2.uri) in manager._tools + + def test_get_tool_by_name_with_custom_uri(self): + """Test getting tools by name when they have custom URIs.""" + + def calculator(x: int, y: int) -> int: + return x + y + + def formatter(text: str) -> str: + return text.upper() + + manager = ToolManager() + + # Add tools with custom URIs + calc_tool = manager.add_tool(calculator, uri="mcp://tools/utils/calculator") + format_tool = manager.add_tool(formatter, uri="mcp://tools/text/formatter") + + # Should be able to get by name + tool_by_name = manager.get_tool("calculator") + assert tool_by_name is not None + assert tool_by_name == calc_tool + + # Should also work for the second tool + tool_by_name2 = manager.get_tool("formatter") + assert tool_by_name2 is not None + assert tool_by_name2 == format_tool + + # Should also be able to get by URI + tool_by_uri = manager.get_tool("mcp://tools/utils/calculator") + assert tool_by_uri == calc_tool + + # Get by AnyUrl + tool_by_anyurl = manager.get_tool(AnyUrl("mcp://tools/text/formatter")) + assert tool_by_anyurl == format_tool + + @pytest.mark.anyio + async def test_tool_name_lookup_with_hierarchical_uri(self): + """Test name lookup works correctly with hierarchical URIs.""" + + def add(a: int, b: int) -> int: + """Add two numbers.""" + return a + b + + def multiply(a: int, b: int) -> int: + """Multiply two numbers.""" + return a * b + + def concat(a: str, b: str) -> str: + """Concatenate strings.""" + return a + b + + manager = ToolManager() + + # Add tools with hierarchical URIs + _ = manager.add_tool(add, uri="mcp://tools/math/add") + _ = manager.add_tool(multiply, uri="mcp://tools/math/multiply") + _ = manager.add_tool(concat, uri="mcp://tools/string/concat") + + # Test calling by name + result = await manager.call_tool("add", {"a": 5, "b": 3}) + assert result == 8 + + result = await manager.call_tool("multiply", {"a": 4, "b": 6}) + assert result == 24 + + result = await manager.call_tool("concat", {"a": "Hello, ", "b": "World!"}) + assert result == "Hello, World!" + + # Test calling by full URI + result = await manager.call_tool("mcp://tools/math/add", {"a": 10, "b": 20}) + assert result == 30 + + result = await manager.call_tool(AnyUrl("mcp://tools/string/concat"), {"a": "Foo", "b": "Bar"}) + assert result == "FooBar" + + # Verify that the standard normalization doesn't work + # (since tools are at custom URIs, not standard ones) + tool = manager.get_tool(f"{TOOL_SCHEME}/add") + assert tool is None # Should not find it at the standard URI + class TestCallTools: @pytest.mark.anyio @@ -354,9 +457,7 @@ def math_multiply(a: int, b: int) -> int: manager.add_tool(math_add) # Add tool with custom URI - multiply_tool = Tool.from_function(math_multiply) - multiply_tool.uri = AnyUrl(f"{TOOL_SCHEME}/custom/math/multiply") - manager._tools[str(multiply_tool.uri)] = multiply_tool + manager.add_tool(math_multiply, uri=f"{TOOL_SCHEME}/custom/math/multiply") # Call by default URI (TOOL_SCHEME/function_name) result = await manager.call_tool(f"{TOOL_SCHEME}/math_add", {"a": 5, "b": 3}) @@ -370,6 +471,10 @@ def math_multiply(a: int, b: int) -> int: result = await manager.call_tool("math_add", {"a": 2, "b": 2}) assert result == 4 + # Custom URI tool should also work with name + result = await manager.call_tool("math_multiply", {"a": 3, "b": 3}) + assert result == 9 + def test_get_tool_by_uri(self): """Test getting tools by their URI.""" diff --git a/types_protocol_changes.md b/types_protocol_changes.md deleted file mode 100644 index 2a135e67e..000000000 --- a/types_protocol_changes.md +++ /dev/null @@ -1,73 +0,0 @@ -# Protocol Changes in types.py - -## URI Standardization - -### Added URI schemes - -```python -MCP_SCHEME = "mcp" -TOOL_SCHEME = "mcp://tools" -PROMPT_SCHEME = "mcp://prompts" -``` - -## Request/Response Changes - -### Renamed pagination to list-based naming - -```python -# Before -class PaginatedRequestParams(RequestParams): - cursor: Cursor | None = None - -class PaginatedRequest(Request[PaginatedRequestParams | None, MethodT]) -class PaginatedResult(Result) - -# After -class ListRequestParams(RequestParams): - prefix: str | None = None # NEW: prefix filtering - cursor: Cursor | None = None - -class ListRequest(Request[ListRequestParams | None, MethodT]) -class ListResult(Result) -``` - -## Tool Protocol Changes - -### Tool now includes URI - -```python -class Tool(BaseMetadata): - uri: AnyUrl | None = None # NEW: auto-generated as mcp://tools/{name} - description: str | None = None - inputSchema: dict[str, Any] -``` - -## Prompt Protocol Changes - -### Prompt now includes URI - -```python -class Prompt(BaseMetadata): - uri: AnyUrl | None = None # NEW: auto-generated as mcp://prompts/{name} - description: str | None = None - arguments: list[PromptArgument] | None = None -``` - -## Resource Validation - -### Resources cannot use tool/prompt URI schemes - -```python -@model_validator(mode="after") -def validate_uri_scheme(self) -> "Resource": - # Prevents resources from using mcp://tools or mcp://prompts -``` - -## List Methods Update - -All list requests now support prefix filtering: - -- `ListResourcesRequest` -- `ListToolsRequest` -- `ListPromptsRequest` -- `ListResourceTemplatesRequest`