Coverage for mcpgateway / common / models.py: 99%
344 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-11 07:10 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-11 07:10 +0000
1# -*- coding: utf-8 -*-
2"""Location: ./mcpgateway/models.py
3Copyright 2025
4SPDX-License-Identifier: Apache-2.0
5Authors: Mihai Criveti
7MCP Protocol Type Definitions.
8This module defines all core MCP protocol types according to the specification.
9It includes:
10 - Message content types (text, image, resource)
11 - Tool definitions and schemas
12 - Resource types and templates
13 - Prompt structures
14 - Protocol initialization types
15 - Sampling message types
16 - Capability definitions
18Examples:
19 >>> from mcpgateway.common.models import Role, LogLevel, TextContent
20 >>> Role.USER.value
21 'user'
22 >>> Role.ASSISTANT.value
23 'assistant'
24 >>> LogLevel.ERROR.value
25 'error'
26 >>> LogLevel.INFO.value
27 'info'
28 >>> content = TextContent(type='text', text='Hello')
29 >>> content.text
30 'Hello'
31 >>> content.type
32 'text'
33"""
35# Standard
36from datetime import datetime
37from enum import Enum
38from typing import Any, Dict, List, Literal, Optional, Union
40# Third-Party
41from pydantic import AnyHttpUrl, AnyUrl, BaseModel, ConfigDict, Field
43# First-Party
44from mcpgateway.utils.base_models import BaseModelWithConfigDict, to_camel_case
47class Role(str, Enum):
48 """Message role in conversations.
50 Attributes:
51 ASSISTANT (str): Indicates the assistant's role.
52 USER (str): Indicates the user's role.
54 Examples:
55 >>> Role.USER.value
56 'user'
57 >>> Role.ASSISTANT.value
58 'assistant'
59 >>> Role.USER == 'user'
60 True
61 >>> list(Role)
62 [<Role.ASSISTANT: 'assistant'>, <Role.USER: 'user'>]
63 """
65 ASSISTANT = "assistant"
66 USER = "user"
69class LogLevel(str, Enum):
70 """Standard syslog severity levels as defined in RFC 5424.
72 Attributes:
73 DEBUG (str): Debug level.
74 INFO (str): Informational level.
75 NOTICE (str): Notice level.
76 WARNING (str): Warning level.
77 ERROR (str): Error level.
78 CRITICAL (str): Critical level.
79 ALERT (str): Alert level.
80 EMERGENCY (str): Emergency level.
81 """
83 DEBUG = "debug"
84 INFO = "info"
85 NOTICE = "notice"
86 WARNING = "warning"
87 ERROR = "error"
88 CRITICAL = "critical"
89 ALERT = "alert"
90 EMERGENCY = "emergency"
93# MCP Protocol Annotations
94class Annotations(BaseModel):
95 """Optional annotations for client rendering hints (MCP spec-compliant).
97 Attributes:
98 audience (Optional[List[Role]]): Describes who the intended customer of this
99 object or data is. Can include multiple entries
100 (e.g., ["user", "assistant"]).
101 priority (Optional[float]): Describes how important this data is for operating
102 the server. 1 = most important (effectively required),
103 0 = least important (entirely optional).
104 last_modified (Optional[str]): ISO 8601 timestamp of last modification.
105 Serialized as 'lastModified' in JSON.
106 """
108 audience: Optional[List[Role]] = None
109 priority: Optional[float] = Field(None, ge=0, le=1)
110 last_modified: Optional[str] = Field(None, alias="lastModified")
112 model_config = ConfigDict(populate_by_name=True)
115class ToolAnnotations(BaseModel):
116 """Tool behavior hints for clients (MCP spec-compliant).
118 Attributes:
119 title (Optional[str]): Human-readable display name for the tool.
120 read_only_hint (Optional[bool]): If true, tool does not modify its environment.
121 destructive_hint (Optional[bool]): If true, tool may perform destructive updates.
122 Only meaningful when read_only_hint == false.
123 idempotent_hint (Optional[bool]): If true, calling repeatedly with same arguments
124 has no additional effect. Only meaningful when
125 read_only_hint == false.
126 open_world_hint (Optional[bool]): If true, tool may interact with an "open world"
127 of external entities (e.g., web search).
128 """
130 title: Optional[str] = None
131 read_only_hint: Optional[bool] = Field(None, alias="readOnlyHint")
132 destructive_hint: Optional[bool] = Field(None, alias="destructiveHint")
133 idempotent_hint: Optional[bool] = Field(None, alias="idempotentHint")
134 open_world_hint: Optional[bool] = Field(None, alias="openWorldHint")
136 model_config = ConfigDict(populate_by_name=True)
139# Base content types
140class TextContent(BaseModelWithConfigDict):
141 """Text content for messages (MCP spec-compliant).
143 Attributes:
144 type (Literal["text"]): The fixed content type identifier for text.
145 text (str): The actual text message.
146 annotations (Optional[Annotations]): Optional annotations for the client.
147 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
148 Serialized as '_meta' in JSON.
150 Examples:
151 >>> content = TextContent(type='text', text='Hello World')
152 >>> content.text
153 'Hello World'
154 >>> content.type
155 'text'
156 >>> content.model_dump(exclude_none=True)
157 {'type': 'text', 'text': 'Hello World'}
158 """
160 type: Literal["text"]
161 text: str
162 annotations: Optional[Annotations] = None
163 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
166class ImageContent(BaseModelWithConfigDict):
167 """Image content for messages (MCP spec-compliant).
169 Attributes:
170 type (Literal["image"]): The fixed content type identifier for images.
171 data (str): Base64-encoded image data for JSON compatibility.
172 mime_type (str): The MIME type (e.g. "image/png") of the image.
173 Will be serialized as 'mimeType' in JSON.
174 annotations (Optional[Annotations]): Optional annotations for the client.
175 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
176 Serialized as '_meta' in JSON.
177 """
179 type: Literal["image"]
180 data: str # Base64-encoded string for JSON compatibility
181 mime_type: str # Will be converted to mimeType by alias_generator
182 annotations: Optional[Annotations] = None
183 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
186class AudioContent(BaseModelWithConfigDict):
187 """Audio content for messages (MCP spec-compliant).
189 Attributes:
190 type (Literal["audio"]): The fixed content type identifier for audio.
191 data (str): Base64-encoded audio data for JSON compatibility.
192 mime_type (str): The MIME type of the audio (e.g., "audio/wav", "audio/mp3").
193 Different providers may support different audio types.
194 Will be serialized as 'mimeType' in JSON.
195 annotations (Optional[Annotations]): Optional annotations for the client.
196 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
197 Serialized as '_meta' in JSON.
198 """
200 type: Literal["audio"]
201 data: str # Base64-encoded string for JSON compatibility
202 mime_type: str # Will be converted to mimeType by alias_generator
203 annotations: Optional[Annotations] = None
204 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
207class ResourceContents(BaseModelWithConfigDict):
208 """Base class for resource contents (MCP spec-compliant).
210 Attributes:
211 uri (str): The URI of the resource.
212 mime_type (Optional[str]): The MIME type of the resource, if known.
213 Will be serialized as 'mimeType' in JSON.
214 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
215 Serialized as '_meta' in JSON.
216 """
218 uri: str
219 mime_type: Optional[str] = Field(None, alias="mimeType")
220 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
223class TextResourceContents(ResourceContents):
224 """Text contents of a resource (MCP spec-compliant).
226 Attributes:
227 text (str): The textual content of the resource.
228 """
230 text: str
233class BlobResourceContents(ResourceContents):
234 """Binary contents of a resource (MCP spec-compliant).
236 Attributes:
237 blob (str): Base64-encoded binary data of the resource.
238 """
240 blob: str # Base64-encoded binary data
243# Legacy ResourceContent for backwards compatibility
244class ResourceContent(BaseModel):
245 """Resource content that can be embedded (LEGACY - use TextResourceContents or BlobResourceContents).
247 This class is maintained for backwards compatibility but does not fully comply
248 with the MCP spec. New code should use TextResourceContents or BlobResourceContents.
250 Attributes:
251 type (Literal["resource"]): The fixed content type identifier for resources.
252 id (str): The ID identifying the resource.
253 uri (str): The URI of the resource.
254 mime_type (Optional[str]): The MIME type of the resource, if known.
255 text (Optional[str]): A textual representation of the resource, if applicable.
256 blob (Optional[bytes]): Binary data of the resource, if applicable.
257 """
259 type: Literal["resource"]
260 id: str
261 uri: str
262 mime_type: Optional[str] = None
263 text: Optional[str] = None
264 blob: Optional[bytes] = None
267ContentType = Union[TextContent, ImageContent, ResourceContent]
270# Reference types - needed early for completion
271class PromptReference(BaseModel):
272 """Reference to a prompt or prompt template.
274 Attributes:
275 type (Literal["ref/prompt"]): The fixed reference type identifier for prompts.
276 name (str): The unique name of the prompt.
277 """
279 type: Literal["ref/prompt"]
280 name: str
283class ResourceReference(BaseModel):
284 """Reference to a resource or resource template.
286 Attributes:
287 type (Literal["ref/resource"]): The fixed reference type identifier for resources.
288 uri (str): The URI of the resource.
289 """
291 type: Literal["ref/resource"]
292 uri: str
295# Completion types
296class CompleteRequest(BaseModel):
297 """Request for completion suggestions.
299 Attributes:
300 ref (Union[PromptReference, ResourceReference]): A reference to a prompt or resource.
301 argument (Dict[str, str]): A dictionary containing arguments for the completion.
302 """
304 ref: Union[PromptReference, ResourceReference]
305 argument: Dict[str, str]
308class CompleteResult(BaseModel):
309 """Result for a completion request.
311 Attributes:
312 completion (Dict[str, Any]): A dictionary containing the completion results.
313 """
315 completion: Dict[str, Any] = Field(..., description="Completion results")
318# Implementation info
319class Implementation(BaseModel):
320 """MCP implementation information.
322 Attributes:
323 name (str): The name of the implementation.
324 version (str): The version of the implementation.
325 """
327 name: str
328 version: str
331# Model preferences
332class ModelHint(BaseModel):
333 """Hint for model selection.
335 Attributes:
336 name (Optional[str]): An optional hint for the model name.
337 """
339 name: Optional[str] = None
342class ModelPreferences(BaseModelWithConfigDict):
343 """Server preferences for model selection.
345 Uses BaseModelWithConfigDict for automatic snake_case → camelCase conversion.
346 Fields serialize as: costPriority, speedPriority, intelligencePriority.
348 Attributes:
349 cost_priority (float): Priority for cost efficiency (0 to 1).
350 speed_priority (float): Priority for speed (0 to 1).
351 intelligence_priority (float): Priority for intelligence (0 to 1).
352 hints (List[ModelHint]): A list of model hints.
353 """
355 cost_priority: float = Field(ge=0, le=1)
356 speed_priority: float = Field(ge=0, le=1)
357 intelligence_priority: float = Field(ge=0, le=1)
358 hints: List[ModelHint] = []
361# Capability types
362class ClientCapabilities(BaseModel):
363 """Capabilities that a client may support.
365 Attributes:
366 roots (Optional[Dict[str, bool]]): Capabilities related to root management.
367 sampling (Optional[Dict[str, Any]]): Capabilities related to LLM sampling.
368 elicitation (Optional[Dict[str, Any]]): Capabilities related to elicitation (MCP 2025-06-18).
369 experimental (Optional[Dict[str, Dict[str, Any]]]): Experimental capabilities.
370 """
372 roots: Optional[Dict[str, bool]] = None
373 sampling: Optional[Dict[str, Any]] = None
374 elicitation: Optional[Dict[str, Any]] = None
375 experimental: Optional[Dict[str, Dict[str, Any]]] = None
378class ServerCapabilities(BaseModel):
379 """Capabilities that a server may support.
381 Attributes:
382 prompts (Optional[Dict[str, bool]]): Capability for prompt support.
383 resources (Optional[Dict[str, bool]]): Capability for resource support.
384 tools (Optional[Dict[str, bool]]): Capability for tool support.
385 logging (Optional[Dict[str, Any]]): Capability for logging support.
386 completions (Optional[Dict[str, Any]]): Capability for completion support.
387 experimental (Optional[Dict[str, Dict[str, Any]]]): Experimental capabilities.
388 """
390 prompts: Optional[Dict[str, bool]] = None
391 resources: Optional[Dict[str, bool]] = None
392 tools: Optional[Dict[str, bool]] = None
393 logging: Optional[Dict[str, Any]] = None
394 completions: Optional[Dict[str, Any]] = None
395 experimental: Optional[Dict[str, Dict[str, Any]]] = None
398# Initialization types
399class InitializeRequest(BaseModel):
400 """Initial request sent from the client to the server.
402 Attributes:
403 protocol_version (str): The protocol version (alias: protocolVersion).
404 capabilities (ClientCapabilities): The client's capabilities.
405 client_info (Implementation): The client's implementation information (alias: clientInfo).
407 Note:
408 The alias settings allow backward compatibility with older Pydantic versions.
409 """
411 protocol_version: str = Field(..., alias="protocolVersion")
412 capabilities: ClientCapabilities
413 client_info: Implementation = Field(..., alias="clientInfo")
415 model_config = ConfigDict(
416 populate_by_name=True,
417 )
420class InitializeResult(BaseModel):
421 """Server's response to the initialization request.
423 Attributes:
424 protocol_version (str): The protocol version used.
425 capabilities (ServerCapabilities): The server's capabilities.
426 server_info (Implementation): The server's implementation information.
427 instructions (Optional[str]): Optional instructions for the client.
428 """
430 protocol_version: str = Field(..., alias="protocolVersion")
431 capabilities: ServerCapabilities = Field(..., alias="capabilities")
432 server_info: Implementation = Field(..., alias="serverInfo")
433 instructions: Optional[str] = Field(None, alias="instructions")
435 model_config = ConfigDict(
436 populate_by_name=True,
437 )
440# Message types
441class Message(BaseModel):
442 """A message in a conversation.
444 Attributes:
445 role (Role): The role of the message sender.
446 content (ContentType): The content of the message.
447 """
449 role: Role
450 content: ContentType
453class SamplingMessage(BaseModel):
454 """A message used in LLM sampling requests.
456 Attributes:
457 role (Role): The role of the sender.
458 content (ContentType): The content of the sampling message.
459 """
461 role: Role
462 content: ContentType
465class PromptMessage(BaseModelWithConfigDict):
466 """Message in a prompt (MCP spec-compliant).
468 A PromptMessage is similar to SamplingMessage but can include additional
469 content types like ResourceLink and EmbeddedResource.
471 Attributes:
472 role (Role): The role of the sender (user or assistant).
473 content (ContentBlock): The content of the prompt message.
474 Supports text, images, audio, resource links, and embedded resources.
476 Note:
477 Per MCP spec, PromptMessage differs from SamplingMessage in that it can
478 include ResourceLink and EmbeddedResource content types.
479 """
481 role: Role
482 content: "ContentBlock" # Uses ContentBlock union (includes ResourceLink and EmbeddedResource)
485# Sampling types for the client features
486class CreateMessageResult(BaseModelWithConfigDict):
487 """Result from a sampling/createMessage request.
489 Uses BaseModelWithConfigDict for automatic snake_case → camelCase conversion.
490 The stop_reason field serializes as stopReason per MCP spec.
492 Attributes:
493 content (Union[TextContent, ImageContent]): The generated content.
494 model (str): The model used for generating the content.
495 role (Role): The role associated with the content.
496 stop_reason (Optional[str]): An optional reason for why sampling stopped.
497 """
499 content: Union[TextContent, ImageContent]
500 model: str
501 role: Role
502 stop_reason: Optional[str] = None
505# Prompt types
506class PromptArgument(BaseModelWithConfigDict):
507 """An argument that can be passed to a prompt (MCP spec-compliant, extends BaseMetadata).
509 Attributes:
510 name (str): The name of the argument.
511 title (Optional[str]): Human-readable title for the argument.
512 description (Optional[str]): An optional description of the argument.
513 required (bool): Whether the argument is required. Defaults to False.
514 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
515 Serialized as '_meta' in JSON.
516 """
518 name: str
519 title: Optional[str] = None
520 description: Optional[str] = None
521 required: bool = False
522 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
525class Prompt(BaseModelWithConfigDict):
526 """A prompt template offered by the server (MCP spec-compliant).
528 Attributes:
529 name (str): The unique name of the prompt.
530 description (Optional[str]): A description of the prompt.
531 arguments (List[PromptArgument]): A list of expected prompt arguments.
532 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
533 Serialized as '_meta' in JSON.
534 """
536 name: str
537 description: Optional[str] = None
538 arguments: List[PromptArgument] = []
539 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
542class PromptResult(BaseModel):
543 """Result of rendering a prompt template.
545 Attributes:
546 messages (List[Message]): The list of messages produced by rendering the prompt.
547 description (Optional[str]): An optional description of the rendered result.
548 """
550 messages: List[Message]
551 description: Optional[str] = None
554class CommonAttributes(BaseModel):
555 """Common attributes for tools and gateways.
557 Attributes:
558 name (str): The unique name of the tool.
559 url (AnyHttpUrl): The URL of the tool.
560 description (Optional[str]): A description of the tool.
561 created_at (Optional[datetime]): The time at which the tool was created.
562 update_at (Optional[datetime]): The time at which the tool was updated.
563 enabled (Optional[bool]): If the tool is enabled.
564 reachable (Optional[bool]): If the tool is currently reachable.
565 tags (Optional[list[Dict[str,str]]]): A list of meta data tags describing the tool.
566 created_by (Optional[str]): The person that created the tool.
567 created_from_ip (Optional[str]): The client IP that created the tool.
568 created_via (Optional[str]): How the tool was created (e.g., ui).
569 created_user_agent (Optioanl[str]): The client user agent.
570 modified_by (Optional[str]): The person that modified the tool.
571 modified_from_ip (Optional[str]): The client IP that modified the tool.
572 modified_via (Optional[str]): How the tool was modified (e.g., ui).
573 modified_user_agent (Optioanl[str]): The client user agent.
574 import_batch_id (Optional[str]): The id of the batch file that imported the tool.
575 federation_source (Optional[str]): The federation source of the tool
576 version (Optional[int]): The version of the tool.
577 team_id (Optional[str]): The id of the team that created the tool.
578 owner_email (Optional[str]): Tool owner's email.
579 visibility (Optional[str]): Visibility of the tool (e.g., public, private).
580 """
582 name: str
583 url: AnyHttpUrl
584 description: Optional[str] = None
585 created_at: Optional[datetime] = None
586 updated_at: Optional[datetime] = None
587 enabled: Optional[bool] = None
588 reachable: Optional[bool] = None
589 auth_type: Optional[str] = None
590 tags: Optional[list[Dict[str, str]]] = None
591 # Comprehensive metadata for audit tracking
592 created_by: Optional[str] = None
593 created_from_ip: Optional[str] = None
594 created_via: Optional[str] = None
595 created_user_agent: Optional[str] = None
597 modified_by: Optional[str] = None
598 modified_from_ip: Optional[str] = None
599 modified_via: Optional[str] = None
600 modified_user_agent: Optional[str] = None
602 import_batch_id: Optional[str] = None
603 federation_source: Optional[str] = None
604 version: Optional[int] = None
605 # Team scoping fields for resource organization
606 team_id: Optional[str] = None
607 owner_email: Optional[str] = None
608 visibility: Optional[str] = None
611# Tool types
612class Tool(CommonAttributes):
613 """A tool that can be invoked.
615 Attributes:
616 original_name (str): The original supplied name of the tool before imported by the gateway.
617 integrationType (str): The integration type of the tool (e.g. MCP or REST).
618 requestType (str): The HTTP method used to invoke the tool (GET, POST, PUT, DELETE, SSE, STDIO).
619 headers (Dict[str, Any]): A JSON object representing HTTP headers.
620 input_schema (Dict[str, Any]): A JSON Schema for validating the tool's input.
621 output_schema (Optional[Dict[str, Any]]): A JSON Schema for validating the tool's output.
622 annotations (Optional[Dict[str, Any]]): Tool annotations for behavior hints.
623 auth_username (Optional[str]): The username for basic authentication.
624 auth_password (Optional[str]): The password for basic authentication.
625 auth_token (Optional[str]): The token for bearer authentication.
626 jsonpath_filter (Optional[str]): Filter the tool based on a JSON path expression.
627 custom_name (Optional[str]): Custom tool name.
628 custom_name_slug (Optional[str]): Alternative custom tool name.
629 display_name (Optional[str]): Display name.
630 gateway_id (Optional[str]): The gateway id on which the tool is hosted.
631 """
633 model_config = ConfigDict(from_attributes=True)
634 original_name: Optional[str] = None
635 integration_type: str = "MCP"
636 request_type: str = "SSE"
637 headers: Optional[Dict[str, Any]] = Field(default_factory=dict)
638 input_schema: Dict[str, Any] = Field(default_factory=lambda: {"type": "object", "properties": {}})
639 output_schema: Optional[Dict[str, Any]] = Field(default=None, description="JSON Schema for validating the tool's output")
640 annotations: Optional[Dict[str, Any]] = Field(default_factory=dict, description="Tool annotations for behavior hints")
641 auth_username: Optional[str] = None
642 auth_password: Optional[str] = None
643 auth_token: Optional[str] = None
644 jsonpath_filter: Optional[str] = None
646 # custom_name,custom_name_slug, display_name
647 custom_name: Optional[str] = None
648 custom_name_slug: Optional[str] = None
649 display_name: Optional[str] = None
651 # Federation relationship with a local gateway
652 gateway_id: Optional[str] = None
655class CallToolResult(BaseModelWithConfigDict):
656 """Result of a tool invocation (MCP spec-compliant).
658 Attributes:
659 content (List[ContentType]): A list of content items returned by the tool.
660 is_error (bool): Flag indicating if the tool call resulted in an error.
661 Will be serialized as 'isError' in JSON.
662 structured_content (Optional[Dict[str, Any]]): Optional structured JSON output.
663 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
664 Serialized as '_meta' in JSON.
666 Note:
667 This class uses BaseModelWithConfigDict which automatically converts
668 is_error to isError in JSON output via the alias_generator.
669 """
671 content: List["ContentBlock"] # Uses ContentBlock union for full MCP spec support
672 is_error: Optional[bool] = Field(default=False, alias="isError")
673 structured_content: Optional[Dict[str, Any]] = Field(None, alias="structuredContent")
674 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
677# Legacy alias for backwards compatibility
678ToolResult = CallToolResult
681# Resource types
682class Resource(BaseModelWithConfigDict):
683 """A resource available from the server (MCP spec-compliant).
685 Attributes:
686 uri (str): The unique URI of the resource.
687 name (str): The human-readable name of the resource.
688 description (Optional[str]): A description of the resource.
689 mime_type (Optional[str]): The MIME type of the resource.
690 Will be serialized as 'mimeType' in JSON.
691 size (Optional[int]): The size of the resource.
692 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
693 Serialized as '_meta' in JSON.
694 """
696 uri: str
697 name: str
698 description: Optional[str] = None
699 mime_type: Optional[str] = None
700 size: Optional[int] = None
701 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
704class ResourceTemplate(BaseModelWithConfigDict):
705 """A template for constructing resource URIs (MCP spec-compliant).
707 Attributes:
708 id (Optional[str]): Unique identifier for resource
709 uri_template (str): The URI template string.
710 name (str): The unique name of the template.
711 description (Optional[str]): A description of the template.
712 mime_type (Optional[str]): The MIME type associated with the template.
713 Will be serialized as 'mimeType' in JSON.
714 annotations (Optional[Annotations]): Optional annotations for client rendering hints.
715 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
716 Serialized as '_meta' in JSON.
717 """
719 # ✅ DB field name: uri_template
720 # ✅ API (JSON) alias:
721 id: Optional[str] = None
722 uri_template: str = Field(..., alias="uriTemplate")
723 name: str
724 description: Optional[str] = None
725 mime_type: Optional[str] = None
726 annotations: Optional[Dict[str, Any]] = None
727 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
730class ResourceLink(Resource):
731 """A resource link included in prompts or tool results (MCP spec-compliant).
733 Note: Inherits uri, name, description, mime_type, size, meta from Resource.
734 Per MCP spec, this extends Resource and adds a type discriminator.
736 Attributes:
737 type (Literal["resource_link"]): The fixed type identifier for resource links.
738 """
740 type: Literal["resource_link"] = "resource_link"
743class EmbeddedResource(BaseModelWithConfigDict):
744 """The contents of a resource, embedded into a prompt or tool call result (MCP spec-compliant).
746 It is up to the client how best to render embedded resources for the benefit
747 of the LLM and/or the user.
749 Attributes:
750 type (Literal["resource"]): The fixed type identifier for embedded resources.
751 resource (Union[TextResourceContents, BlobResourceContents]): The resource contents.
752 annotations (Optional[Annotations]): Optional annotations for the client.
753 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
754 Serialized as '_meta' in JSON.
755 """
757 type: Literal["resource"] = "resource"
758 resource: Union[TextResourceContents, BlobResourceContents]
759 annotations: Optional[Annotations] = None
760 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
763# MCP spec-compliant ContentBlock union for prompts and tool results
764# Per spec: ContentBlock can include ResourceLink and EmbeddedResource
765ContentBlock = Union[TextContent, ImageContent, AudioContent, ResourceLink, EmbeddedResource]
768class ListResourceTemplatesResult(BaseModel):
769 """The server's response to a resources/templates/list request from the client.
771 Attributes:
772 meta (Optional[Dict[str, Any]]): Reserved property for metadata.
773 next_cursor (Optional[str]): Pagination cursor for the next page of results.
774 resource_templates (List[ResourceTemplate]): List of resource templates.
775 """
777 meta: Optional[Dict[str, Any]] = Field(
778 None, alias="_meta", description="This result property is reserved by the protocol to allow clients and servers to attach additional metadata to their responses."
779 )
780 next_cursor: Optional[str] = Field(None, description="An opaque token representing the pagination position after the last returned result.\nIf present, there may be more results available.")
781 resource_templates: List[ResourceTemplate] = Field(default_factory=list, description="List of resource templates available on the server")
783 model_config = ConfigDict(
784 populate_by_name=True,
785 )
788# Elicitation types (MCP 2025-06-18)
789class ElicitationCapability(BaseModelWithConfigDict):
790 """Client capability for elicitation operations (MCP 2025-06-18).
792 Per MCP spec: Clients that support elicitation MUST declare this capability
793 during initialization. Elicitation allows servers to request structured
794 information from users through the client during interactive workflows.
796 Example:
797 {"capabilities": {"elicitation": {}}}
798 """
800 # Empty object per MCP spec, follows MCP SDK pattern
801 model_config = ConfigDict(extra="allow")
804class ElicitRequestParams(BaseModelWithConfigDict):
805 """Parameters for elicitation/create requests (MCP spec-compliant).
807 Elicitation requests allow servers to ask for user input with a structured
808 schema. The schema is restricted to flat objects with primitive types only.
810 Attributes:
811 message: Human-readable message to present to user
812 requestedSchema: JSON Schema defining expected response structure.
813 Per MCP spec, must be type 'object' with primitive properties only:
814 - string (optional format: email, uri, date, date-time)
815 - number/integer (optional min/max)
816 - boolean
817 - enum (string values)
818 No nested objects or arrays allowed.
820 Example:
821 {
822 "message": "Please provide your contact information",
823 "requestedSchema": {
824 "type": "object",
825 "properties": {
826 "name": {"type": "string", "description": "Your full name"},
827 "email": {"type": "string", "format": "email"}
828 },
829 "required": ["name", "email"]
830 }
831 }
832 """
834 message: str
835 requestedSchema: Dict[str, Any] # JSON Schema (validated by ElicitationService) # noqa: N815 (MCP spec requires camelCase)
836 model_config = ConfigDict(extra="allow")
839class ElicitResult(BaseModelWithConfigDict):
840 """Client response to elicitation request (MCP spec three-action model).
842 The MCP specification defines three distinct user actions to differentiate
843 between explicit approval, explicit rejection, and dismissal without choice.
845 Attributes:
846 action: User's response action:
847 - "accept": User explicitly approved and submitted data
848 (content field MUST be populated)
849 - "decline": User explicitly declined the request
850 (content typically None/omitted)
851 - "cancel": User dismissed without making an explicit choice
852 (content typically None/omitted)
853 content: Submitted form data matching requestedSchema.
854 Only present when action is "accept".
855 Contains primitive values: str, int, float, bool, or None.
857 Examples:
858 Accept response:
859 {"action": "accept", "content": {"name": "John", "email": "john@example.com"}}
861 Decline response:
862 {"action": "decline"}
864 Cancel response:
865 {"action": "cancel"}
866 """
868 action: Literal["accept", "decline", "cancel"]
869 content: Optional[Dict[str, Union[str, int, float, bool, None]]] = None
870 model_config = ConfigDict(extra="allow")
873# Root types
874class FileUrl(AnyUrl):
875 """A specialized URL type for local file-scheme resources.
877 Key characteristics
878 -------------------
879 * Scheme restricted - only the "file" scheme is permitted
880 (e.g. file:///path/to/file.txt).
881 * No host required - "file" URLs typically omit a network host;
882 therefore, the host component is not mandatory.
883 * String-friendly equality - developers naturally expect
884 FileUrl("file:///data") == "file:///data" to evaluate True.
885 AnyUrl (Pydantic) does not implement that, so we override
886 __eq__ to compare against plain strings transparently.
887 Hash semantics are kept consistent by delegating to the parent class.
889 Examples
890 --------
891 >>> url = FileUrl("file:///etc/hosts")
892 >>> url.scheme
893 'file'
894 >>> url == "file:///etc/hosts"
895 True
896 >>> {"path": url} # hashable
897 {'path': FileUrl('file:///etc/hosts')}
899 Notes
900 -----
901 The override does not interfere with comparisons to other
902 AnyUrl/FileUrl instances; those still use the superclass
903 implementation.
904 """
906 # Restrict to the "file" scheme and omit host requirement
907 allowed_schemes = {"file"}
908 host_required = False
910 def __eq__(self, other): # type: ignore[override]
911 """Return True when other is an equivalent URL or string.
913 If other is a str it is coerced with str(self) for comparison;
914 otherwise defer to AnyUrl's comparison.
916 Args:
917 other (Any): The object to compare against. May be a str, FileUrl, or AnyUrl.
919 Returns:
920 bool: True if the other value is equal to this URL, either as a string
921 or as another URL object. False otherwise.
922 """
923 if isinstance(other, str): 923 ↛ 925line 923 didn't jump to line 925 because the condition on line 923 was always true
924 return str(self) == other
925 return super().__eq__(other)
927 # Keep hashing behaviour aligned with equality
928 __hash__ = AnyUrl.__hash__
931class Root(BaseModelWithConfigDict):
932 """A root directory or file (MCP spec-compliant).
934 Attributes:
935 uri (Union[FileUrl, AnyUrl]): The unique identifier for the root.
936 name (Optional[str]): An optional human-readable name.
937 meta (Optional[Dict[str, Any]]): Optional metadata for protocol extension.
938 Serialized as '_meta' in JSON.
939 """
941 model_config = ConfigDict(
942 arbitrary_types_allowed=True,
943 from_attributes=True,
944 alias_generator=to_camel_case,
945 populate_by_name=True,
946 use_enum_values=True,
947 extra="ignore",
948 json_schema_extra={"nullable": True},
949 )
951 uri: Union[FileUrl, AnyUrl] = Field(..., description="Unique identifier for the root")
952 name: Optional[str] = Field(None, description="Optional human-readable name")
953 meta: Optional[Dict[str, Any]] = Field(None, alias="_meta")
956# Progress types
957class ProgressToken(BaseModel):
958 """Token for associating progress notifications.
960 Attributes:
961 value (Union[str, int]): The token value.
962 """
964 value: Union[str, int]
967class Progress(BaseModel):
968 """Progress update for long-running operations.
970 Attributes:
971 progress_token (ProgressToken): The token associated with the progress update.
972 progress (float): The current progress value.
973 total (Optional[float]): The total progress value, if known.
974 """
976 progress_token: ProgressToken
977 progress: float
978 total: Optional[float] = None
981# JSON-RPC types
982class JSONRPCRequest(BaseModel):
983 """JSON-RPC 2.0 request.
985 Attributes:
986 jsonrpc (Literal["2.0"]): The JSON-RPC version.
987 id (Optional[Union[str, int]]): The request identifier.
988 method (str): The method name.
989 params (Optional[Dict[str, Any]]): The parameters for the request.
990 """
992 jsonrpc: Literal["2.0"]
993 id: Optional[Union[str, int]] = None
994 method: str
995 params: Optional[Dict[str, Any]] = None
998class JSONRPCResponse(BaseModel):
999 """JSON-RPC 2.0 response.
1001 Attributes:
1002 jsonrpc (Literal["2.0"]): The JSON-RPC version.
1003 id (Optional[Union[str, int]]): The request identifier.
1004 result (Optional[Any]): The result of the request.
1005 error (Optional[Dict[str, Any]]): The error object if an error occurred.
1006 """
1008 jsonrpc: Literal["2.0"]
1009 id: Optional[Union[str, int]] = None
1010 result: Optional[Any] = None
1011 error: Optional[Dict[str, Any]] = None
1014class JSONRPCError(BaseModel):
1015 """JSON-RPC 2.0 error.
1017 Attributes:
1018 code (int): The error code.
1019 message (str): A short description of the error.
1020 data (Optional[Any]): Additional data about the error.
1021 """
1023 code: int
1024 message: str
1025 data: Optional[Any] = None
1028# Global configuration types
1029class GlobalConfig(BaseModel):
1030 """Global server configuration.
1032 Attributes:
1033 passthrough_headers (Optional[List[str]]): List of headers allowed to be passed through globally
1034 """
1036 passthrough_headers: Optional[List[str]] = Field(default=None, description="List of headers allowed to be passed through globally")
1039# Transport message types
1040class SSEEvent(BaseModel):
1041 """Server-Sent Events message.
1043 Attributes:
1044 id (Optional[str]): The event identifier.
1045 event (Optional[str]): The event type.
1046 data (str): The event data.
1047 retry (Optional[int]): The retry timeout in milliseconds.
1048 """
1050 id: Optional[str] = None
1051 event: Optional[str] = None
1052 data: str
1053 retry: Optional[int] = None
1056class WebSocketMessage(BaseModel):
1057 """WebSocket protocol message.
1059 Attributes:
1060 type (str): The type of the WebSocket message.
1061 data (Any): The message data.
1062 """
1064 type: str
1065 data: Any
1068# Notification types
1069class ResourceUpdateNotification(BaseModel):
1070 """Notification of resource changes.
1072 Attributes:
1073 method (Literal["notifications/resources/updated"]): The notification method.
1074 uri (str): The URI of the updated resource.
1075 """
1077 method: Literal["notifications/resources/updated"]
1078 uri: str
1081class ResourceListChangedNotification(BaseModel):
1082 """Notification of resource list changes.
1084 Attributes:
1085 method (Literal["notifications/resources/list_changed"]): The notification method.
1086 """
1088 method: Literal["notifications/resources/list_changed"]
1091class PromptListChangedNotification(BaseModel):
1092 """Notification of prompt list changes.
1094 Attributes:
1095 method (Literal["notifications/prompts/list_changed"]): The notification method.
1096 """
1098 method: Literal["notifications/prompts/list_changed"]
1101class ToolListChangedNotification(BaseModel):
1102 """Notification of tool list changes.
1104 Attributes:
1105 method (Literal["notifications/tools/list_changed"]): The notification method.
1106 """
1108 method: Literal["notifications/tools/list_changed"]
1111class CancelledNotification(BaseModel):
1112 """Notification of request cancellation.
1114 Attributes:
1115 method (Literal["notifications/cancelled"]): The notification method.
1116 request_id (Union[str, int]): The ID of the cancelled request.
1117 reason (Optional[str]): An optional reason for cancellation.
1118 """
1120 method: Literal["notifications/cancelled"]
1121 request_id: Union[str, int]
1122 reason: Optional[str] = None
1125class ProgressNotification(BaseModel):
1126 """Notification of operation progress.
1128 Attributes:
1129 method (Literal["notifications/progress"]): The notification method.
1130 progress_token (ProgressToken): The token associated with the progress.
1131 progress (float): The current progress value.
1132 total (Optional[float]): The total progress value, if known.
1133 """
1135 method: Literal["notifications/progress"]
1136 progress_token: ProgressToken
1137 progress: float
1138 total: Optional[float] = None
1141class LoggingNotification(BaseModel):
1142 """Notification of log messages.
1144 Attributes:
1145 method (Literal["notifications/message"]): The notification method.
1146 level (LogLevel): The log level of the message.
1147 logger (Optional[str]): The logger name.
1148 data (Any): The log message data.
1149 """
1151 method: Literal["notifications/message"]
1152 level: LogLevel
1153 logger: Optional[str] = None
1154 data: Any
1157# Federation types
1158class FederatedTool(Tool):
1159 """A tool from a federated gateway.
1161 Attributes:
1162 gateway_id (str): The identifier of the gateway.
1163 gateway_name (str): The name of the gateway.
1164 """
1166 gateway_id: str
1167 gateway_name: str
1170class FederatedResource(Resource):
1171 """A resource from a federated gateway.
1173 Attributes:
1174 gateway_id (str): The identifier of the gateway.
1175 gateway_name (str): The name of the gateway.
1176 """
1178 gateway_id: str
1179 gateway_name: str
1182class FederatedPrompt(Prompt):
1183 """A prompt from a federated gateway.
1185 Attributes:
1186 gateway_id (str): The identifier of the gateway.
1187 gateway_name (str): The name of the gateway.
1188 """
1190 gateway_id: str
1191 gateway_name: str
1194class Gateway(CommonAttributes):
1195 """A federated gateway peer.
1197 Attributes:
1198 id (str): The unique identifier for the gateway.
1199 name (str): The name of the gateway.
1200 url (AnyHttpUrl): The URL of the gateway.
1201 capabilities (ServerCapabilities): The capabilities of the gateway.
1202 last_seen (Optional[datetime]): Timestamp when the gateway was last seen.
1203 """
1205 model_config = ConfigDict(from_attributes=True)
1206 id: str
1207 capabilities: ServerCapabilities
1208 last_seen: Optional[datetime] = None
1209 slug: str
1210 transport: str
1211 last_seen: Optional[datetime]
1212 # Header passthrough configuration
1213 passthrough_headers: Optional[list[str]] # Store list of strings as JSON array
1214 # Request type and authentication fields
1215 auth_value: Optional[str | dict]
1218# ===== RBAC Models =====
1221class RBACRole(BaseModel):
1222 """Role model for RBAC system.
1224 Represents roles that can be assigned to users with specific permissions.
1225 Supports global, team, and personal scopes with role inheritance.
1227 Attributes:
1228 id: Unique role identifier
1229 name: Human-readable role name
1230 description: Role description and purpose
1231 scope: Role scope ('global', 'team', 'personal')
1232 permissions: List of permission strings
1233 inherits_from: Parent role ID for inheritance
1234 created_by: Email of user who created the role
1235 is_system_role: Whether this is a system-defined role
1236 is_active: Whether the role is currently active
1237 created_at: Role creation timestamp
1238 updated_at: Role last modification timestamp
1240 Examples:
1241 >>> from datetime import datetime
1242 >>> role = RBACRole(
1243 ... id="role-123",
1244 ... name="team_admin",
1245 ... description="Team administrator with member management rights",
1246 ... scope="team",
1247 ... permissions=["teams.manage_members", "resources.create"],
1248 ... created_by="admin@example.com",
1249 ... created_at=datetime(2023, 1, 1),
1250 ... updated_at=datetime(2023, 1, 1)
1251 ... )
1252 >>> role.name
1253 'team_admin'
1254 >>> "teams.manage_members" in role.permissions
1255 True
1256 """
1258 id: str = Field(..., description="Unique role identifier")
1259 name: str = Field(..., description="Human-readable role name")
1260 description: Optional[str] = Field(None, description="Role description and purpose")
1261 scope: str = Field(..., description="Role scope", pattern="^(global|team|personal)$")
1262 permissions: List[str] = Field(..., description="List of permission strings")
1263 inherits_from: Optional[str] = Field(None, description="Parent role ID for inheritance")
1264 created_by: str = Field(..., description="Email of user who created the role")
1265 is_system_role: bool = Field(False, description="Whether this is a system-defined role")
1266 is_active: bool = Field(True, description="Whether the role is currently active")
1267 created_at: datetime = Field(..., description="Role creation timestamp")
1268 updated_at: datetime = Field(..., description="Role last modification timestamp")
1271class UserRoleAssignment(BaseModel):
1272 """User role assignment model.
1274 Represents the assignment of roles to users in specific scopes (global, team, personal).
1275 Includes metadata about who granted the role and when it expires.
1277 Attributes:
1278 id: Unique assignment identifier
1279 user_email: Email of the user assigned the role
1280 role_id: ID of the assigned role
1281 scope: Assignment scope ('global', 'team', 'personal')
1282 scope_id: Team ID if team-scoped, None otherwise
1283 granted_by: Email of user who granted this role
1284 granted_at: Timestamp when role was granted
1285 expires_at: Optional expiration timestamp
1286 is_active: Whether the assignment is currently active
1288 Examples:
1289 >>> from datetime import datetime
1290 >>> user_role = UserRoleAssignment(
1291 ... id="assignment-123",
1292 ... user_email="user@example.com",
1293 ... role_id="team-admin-123",
1294 ... scope="team",
1295 ... scope_id="team-engineering-456",
1296 ... granted_by="admin@example.com",
1297 ... granted_at=datetime(2023, 1, 1)
1298 ... )
1299 >>> user_role.scope
1300 'team'
1301 >>> user_role.is_active
1302 True
1303 """
1305 id: str = Field(..., description="Unique assignment identifier")
1306 user_email: str = Field(..., description="Email of the user assigned the role")
1307 role_id: str = Field(..., description="ID of the assigned role")
1308 scope: str = Field(..., description="Assignment scope", pattern="^(global|team|personal)$")
1309 scope_id: Optional[str] = Field(None, description="Team ID if team-scoped, None otherwise")
1310 granted_by: str = Field(..., description="Email of user who granted this role")
1311 granted_at: datetime = Field(..., description="Timestamp when role was granted")
1312 expires_at: Optional[datetime] = Field(None, description="Optional expiration timestamp")
1313 is_active: bool = Field(True, description="Whether the assignment is currently active")
1316class PermissionAudit(BaseModel):
1317 """Permission audit log model.
1319 Records all permission checks for security auditing and compliance.
1320 Includes details about the user, permission, resource, and result.
1322 Attributes:
1323 id: Unique audit log entry identifier
1324 timestamp: When the permission check occurred
1325 user_email: Email of user being checked
1326 permission: Permission being checked (e.g., 'tools.create')
1327 resource_type: Type of resource (e.g., 'tools', 'teams')
1328 resource_id: Specific resource ID if applicable
1329 team_id: Team context if applicable
1330 granted: Whether permission was granted
1331 roles_checked: JSON of roles that were checked
1332 ip_address: IP address of the request
1333 user_agent: User agent string
1335 Examples:
1336 >>> from datetime import datetime
1337 >>> audit_log = PermissionAudit(
1338 ... id=1,
1339 ... timestamp=datetime(2023, 1, 1),
1340 ... user_email="user@example.com",
1341 ... permission="tools.create",
1342 ... resource_type="tools",
1343 ... granted=True,
1344 ... roles_checked={"roles": ["team_admin"]}
1345 ... )
1346 >>> audit_log.granted
1347 True
1348 >>> audit_log.permission
1349 'tools.create'
1350 """
1352 id: int = Field(..., description="Unique audit log entry identifier")
1353 timestamp: datetime = Field(..., description="When the permission check occurred")
1354 user_email: Optional[str] = Field(None, description="Email of user being checked")
1355 permission: str = Field(..., description="Permission being checked")
1356 resource_type: Optional[str] = Field(None, description="Type of resource")
1357 resource_id: Optional[str] = Field(None, description="Specific resource ID if applicable")
1358 team_id: Optional[str] = Field(None, description="Team context if applicable")
1359 granted: bool = Field(..., description="Whether permission was granted")
1360 roles_checked: Optional[Dict] = Field(None, description="JSON of roles that were checked")
1361 ip_address: Optional[str] = Field(None, description="IP address of the request")
1362 user_agent: Optional[str] = Field(None, description="User agent string")
1365# Permission constants are imported from db.py to avoid duplication
1366# Use Permissions class from mcpgateway.db instead of duplicate SystemPermissions
1369class TransportType(str, Enum):
1370 """
1371 Enumeration of supported transport mechanisms for communication between components.
1373 Attributes:
1374 SSE (str): Server-Sent Events transport.
1375 HTTP (str): Standard HTTP-based transport.
1376 STDIO (str): Standard input/output transport.
1377 STREAMABLEHTTP (str): HTTP transport with streaming.
1378 GRPC (str): gRPC transport for external plugins.
1379 """
1381 SSE = "SSE"
1382 HTTP = "HTTP"
1383 STDIO = "STDIO"
1384 STREAMABLEHTTP = "STREAMABLEHTTP"
1385 GRPC = "GRPC"