Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ lint.select = [
"B", # flake8-bugbear
]
lint.ignore = []
exclude = ["src/mcp_optimizer/toolhive/api_models"]
exclude = ["src/mcp_optimizer/toolhive/api_models", "data"]

[tool.ty.src]
exclude = ["tests", "examples"]
exclude = ["tests", "examples", "data"]

[tool.pytest.ini_options]
minversion = "8.0"
Expand Down
2 changes: 1 addition & 1 deletion src/mcp_optimizer/toolhive/api_models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00
43 changes: 26 additions & 17 deletions src/mcp_optimizer/toolhive/api_models/audit.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,48 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field


class Config(BaseModel):
component: Optional[str] = Field(
None, description='Component is the component name to use in audit events'
component: str | None = Field(
None,
description='Component is the component name to use in audit events.\n+optional',
)
enabled: bool | None = Field(
None,
description='Enabled controls whether audit logging is enabled.\nWhen true, enables audit logging with the configured options.\n+kubebuilder:default=false\n+optional',
)
event_types: Optional[list[str]] = Field(
event_types: list[str] | None = Field(
None,
description='EventTypes specifies which event types to audit. If empty, all events are audited.',
alias='eventTypes',
description='EventTypes specifies which event types to audit. If empty, all events are audited.\n+optional',
)
exclude_event_types: Optional[list[str]] = Field(
exclude_event_types: list[str] | None = Field(
None,
description='ExcludeEventTypes specifies which event types to exclude from auditing.\nThis takes precedence over EventTypes.',
alias='excludeEventTypes',
description='ExcludeEventTypes specifies which event types to exclude from auditing.\nThis takes precedence over EventTypes.\n+optional',
)
include_request_data: Optional[bool] = Field(
include_request_data: bool | None = Field(
None,
description='IncludeRequestData determines whether to include request data in audit logs',
alias='includeRequestData',
description='IncludeRequestData determines whether to include request data in audit logs.\n+kubebuilder:default=false\n+optional',
)
include_response_data: Optional[bool] = Field(
include_response_data: bool | None = Field(
None,
description='IncludeResponseData determines whether to include response data in audit logs',
alias='includeResponseData',
description='IncludeResponseData determines whether to include response data in audit logs.\n+kubebuilder:default=false\n+optional',
)
log_file: Optional[str] = Field(
log_file: str | None = Field(
None,
description='LogFile specifies the file path for audit logs. If empty, logs to stdout.',
alias='logFile',
description='LogFile specifies the file path for audit logs. If empty, logs to stdout.\n+optional',
)
max_data_size: Optional[int] = Field(
max_data_size: int | None = Field(
None,
description='MaxDataSize limits the size of request/response data included in audit logs (in bytes)',
alias='maxDataSize',
description='MaxDataSize limits the size of request/response data included in audit logs (in bytes).\n+kubebuilder:default=1024\n+optional',
)
30 changes: 16 additions & 14 deletions src/mcp_optimizer/toolhive/api_models/auth.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,62 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field


class TokenValidatorConfig(BaseModel):
allow_private_ip: Optional[bool] = Field(
allow_private_ip: bool | None = Field(
None,
alias='allowPrivateIP',
description='AllowPrivateIP allows JWKS/OIDC endpoints on private IP addresses',
)
audience: Optional[str] = Field(
audience: str | None = Field(
None, description='Audience is the expected audience for the token'
)
auth_token_file: Optional[str] = Field(
auth_token_file: str | None = Field(
None,
alias='authTokenFile',
description='AuthTokenFile is the path to file containing bearer token for authentication',
)
cacert_path: Optional[str] = Field(
cacert_path: str | None = Field(
None,
alias='cacertPath',
description='CACertPath is the path to the CA certificate bundle for HTTPS requests',
)
client_id: Optional[str] = Field(
client_id: str | None = Field(
None, alias='clientID', description='ClientID is the OIDC client ID'
)
client_secret: Optional[str] = Field(
client_secret: str | None = Field(
None,
alias='clientSecret',
description='ClientSecret is the optional OIDC client secret for introspection',
)
insecure_allow_http: Optional[bool] = Field(
insecure_allow_http: bool | None = Field(
None,
alias='insecureAllowHTTP',
description='InsecureAllowHTTP allows HTTP (non-HTTPS) OIDC issuers for development/testing\nWARNING: This is insecure and should NEVER be used in production',
)
introspection_url: Optional[str] = Field(
introspection_url: str | None = Field(
None,
alias='introspectionURL',
description='IntrospectionURL is the optional introspection endpoint for validating tokens',
)
issuer: Optional[str] = Field(
issuer: str | None = Field(
None,
description='Issuer is the OIDC issuer URL (e.g., https://accounts.google.com)',
)
jwksurl: Optional[str] = Field(
jwksurl: str | None = Field(
None, description='JWKSURL is the URL to fetch the JWKS from'
)
resource_url: Optional[str] = Field(
resource_url: str | None = Field(
None,
alias='resourceURL',
description='ResourceURL is the explicit resource URL for OAuth discovery (RFC 9728)',
)
scopes: list[str] | None = Field(
None,
description='Scopes is the list of OAuth scopes to advertise in the well-known endpoint (RFC 9728)\nIf empty, defaults to ["openid"]',
)
21 changes: 5 additions & 16 deletions src/mcp_optimizer/toolhive/api_models/authz.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field


class CedarConfig(BaseModel):
entities_json: Optional[str] = Field(
None, description='EntitiesJSON is the JSON string representing Cedar entities'
)
policies: Optional[list[str]] = Field(
None, description='Policies is a list of Cedar policy strings'
)


class Config(BaseModel):
cedar: Optional[CedarConfig] = None
type: Optional[str] = Field(
None, description='Type is the type of authorization configuration.'
type: str | None = Field(
None,
description='Type is the type of authorization configuration (e.g., "cedarv1").',
)
version: Optional[str] = Field(
version: str | None = Field(
None, description='Version is the version of the configuration format.'
)
40 changes: 31 additions & 9 deletions src/mcp_optimizer/toolhive/api_models/client.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,50 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00

from __future__ import annotations

from typing import Optional
from enum import StrEnum

from pydantic import BaseModel, Field


class MCPClient(StrEnum):
roo_code = 'roo-code'
cline = 'cline'
cursor = 'cursor'
vs_code_insider = 'vscode-insider'
vs_code = 'vscode'
claude_code = 'claude-code'
windsurf = 'windsurf'
windsurf_jet_brains = 'windsurf-jetbrains'
amp_cli = 'amp-cli'
amp_vs_code = 'amp-vscode'
amp_cursor = 'amp-cursor'
amp_vs_code_insider = 'amp-vscode-insider'
amp_windsurf = 'amp-windsurf'
lm_studio = 'lm-studio'
goose = 'goose'
trae = 'trae'
continue_ = 'continue'
open_code = 'opencode'
kiro = 'kiro'
antigravity = 'antigravity'
zed = 'zed'


class MCPClientStatus(BaseModel):
client_type: Optional[str] = Field(
None, description='ClientType is the type of MCP client'
)
installed: Optional[bool] = Field(
client_type: MCPClient | None = None
installed: bool | None = Field(
None,
description='Installed indicates whether the client is installed on the system',
)
registered: Optional[bool] = Field(
registered: bool | None = Field(
None,
description='Registered indicates whether the client is registered in the ToolHive configuration',
)


class RegisteredClient(BaseModel):
groups: Optional[list[str]] = None
name: Optional[str] = None
groups: list[str] | None = None
name: MCPClient | None = None
43 changes: 19 additions & 24 deletions src/mcp_optimizer/toolhive/api_models/core.py
Original file line number Diff line number Diff line change
@@ -1,65 +1,60 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field

from . import runtime, types


class Workload(BaseModel):
created_at: Optional[str] = Field(
created_at: str | None = Field(
None, description='CreatedAt is the timestamp when the workload was created.'
)
group: Optional[str] = Field(
group: str | None = Field(
None,
description='Group is the name of the group this workload belongs to, if any.',
)
labels: Optional[dict[str, str]] = Field(
labels: dict[str, str] | None = Field(
None,
description='Labels are the container labels (excluding standard ToolHive labels)',
)
name: Optional[str] = Field(
name: str | None = Field(
None,
description='Name is the name of the workload.\nIt is used as a unique identifier.',
)
package: Optional[str] = Field(
package: str | None = Field(
None,
description='Package specifies the Workload Package used to create this Workload.',
)
port: Optional[int] = Field(
port: int | None = Field(
None,
description='Port is the port on which the workload is exposed.\nThis is embedded in the URL.',
)
proxy_mode: Optional[str] = Field(
proxy_mode: str | None = Field(
None,
description='ProxyMode is the proxy mode that clients should use to connect.\nFor stdio transports, this will be the proxy mode (sse or streamable-http).\nFor direct transports (sse/streamable-http), this will be the same as TransportType.',
)
remote: Optional[bool] = Field(
remote: bool | None = Field(
None,
description='Remote indicates whether this is a remote workload (true) or a container workload (false).',
)
status: Optional[str] = Field(
None, description='Status is the current status of the workload.'
)
status_context: Optional[str] = Field(
started_at: str | None = Field(
None,
description="StatusContext provides additional context about the workload's status.\nThe exact meaning is determined by the status and the underlying runtime.",
description='StartedAt is when the container was last started (changes on restart)',
)
tool_type: Optional[str] = Field(
status: runtime.WorkloadStatus | None = None
status_context: str | None = Field(
None,
description='ToolType is the type of tool this workload represents.\nFor now, it will always be "mcp" - representing an MCP server.',
description="StatusContext provides additional context about the workload's status.\nThe exact meaning is determined by the status and the underlying runtime.",
)
tools: Optional[list[str]] = Field(
tools: list[str] | None = Field(
None, description='ToolsFilter is the filter on tools applied to the workload.'
)
transport_type: Optional[str] = Field(
None,
description='TransportType is the type of transport used for this workload.',
)
url: Optional[str] = Field(
transport_type: types.TransportType | None = None
url: str | None = Field(
None,
description='URL is the URL of the workload exposed by the ToolHive proxy.',
)
8 changes: 3 additions & 5 deletions src/mcp_optimizer/toolhive/api_models/groups.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel


class Group(BaseModel):
name: Optional[str] = None
registered_clients: Optional[list[str]] = None
name: str | None = None
registered_clients: list[str] | None = None
8 changes: 3 additions & 5 deletions src/mcp_optimizer/toolhive/api_models/ignore.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
# generated by datamodel-codegen:
# filename: http://127.0.0.1:8080/api/openapi.json
# timestamp: 2025-12-02T00:36:43+00:00
# timestamp: 2026-01-23T00:39:31+00:00

from __future__ import annotations

from typing import Optional

from pydantic import BaseModel, Field


class Config(BaseModel):
load_global: Optional[bool] = Field(
load_global: bool | None = Field(
None, alias='loadGlobal', description='Whether to load global ignore patterns'
)
print_overlays: Optional[bool] = Field(
print_overlays: bool | None = Field(
None,
alias='printOverlays',
description='Whether to print resolved overlay paths for debugging',
Expand Down
Loading