optimizely-opal.opal-tools-sdk 0.1.27.dev0__tar.gz → 0.1.28.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/PKG-INFO +115 -1
  2. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/README.md +114 -0
  3. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/proteus.py +25 -2
  4. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/optimizely_opal.opal_tools_sdk.egg-info/PKG-INFO +115 -1
  5. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/pyproject.toml +1 -1
  6. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/setup.py +1 -1
  7. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/__init__.py +0 -0
  8. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/_registry.py +0 -0
  9. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/auth.py +0 -0
  10. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/decorators.py +0 -0
  11. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/logging.py +0 -0
  12. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/models.py +0 -0
  13. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/service.py +0 -0
  14. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/opal_tools_sdk/ui.py +0 -0
  15. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/optimizely_opal.opal_tools_sdk.egg-info/SOURCES.txt +0 -0
  16. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/optimizely_opal.opal_tools_sdk.egg-info/dependency_links.txt +0 -0
  17. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/optimizely_opal.opal_tools_sdk.egg-info/requires.txt +0 -0
  18. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/optimizely_opal.opal_tools_sdk.egg-info/top_level.txt +0 -0
  19. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/setup.cfg +0 -0
  20. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/tests/test_integration.py +0 -0
  21. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/tests/test_nested_schema.py +0 -0
  22. {optimizely_opal_opal_tools_sdk-0.1.27.dev0 → optimizely_opal_opal_tools_sdk-0.1.28.dev0}/tests/test_proteus.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: optimizely-opal.opal-tools-sdk
3
- Version: 0.1.27.dev0
3
+ Version: 0.1.28.dev0
4
4
  Summary: SDK for creating Opal-compatible tools services
5
5
  Home-page: https://github.com/optimizely/opal-tools-sdk
6
6
  Author: Optimizely
@@ -235,6 +235,120 @@ The response wrapper for islands:
235
235
  - Use `IslandResponse.create([islands])` to create responses
236
236
  - Supports multiple islands per response
237
237
 
238
+ ## Resources & Proteus UI
239
+
240
+ The SDK supports defining MCP resources that serve dynamic UI specifications using the Proteus framework. This enables tools to render rich, interactive interfaces without hardcoded frontend integrations.
241
+
242
+ For the full Proteus component reference and visual designer, see the [Proteus documentation](https://optimizely-axiom.github.io/optiaxiom/guides/proteus/).
243
+
244
+ ### Defining a Resource with `@resource`
245
+
246
+ Use the `@resource` decorator to register a function as an MCP resource:
247
+
248
+ ```python
249
+ from opal_tools_sdk import UI
250
+ from opal_tools_sdk.decorators import resource
251
+
252
+ @resource(
253
+ uri="ui://my-app/create-form",
254
+ name="create-form",
255
+ description="Form for creating new items",
256
+ )
257
+ async def get_create_form():
258
+ return UI.Document(
259
+ title="Create Item",
260
+ body=[
261
+ UI.Heading(children="New Item"),
262
+ UI.Field(
263
+ label="Item Name",
264
+ children=UI.Input(name="item_name", placeholder="Enter item name"),
265
+ ),
266
+ UI.Field(
267
+ label="Description",
268
+ children=UI.Textarea(name="description", placeholder="Enter description"),
269
+ ),
270
+ ],
271
+ actions=[
272
+ UI.Action(children="Save", appearance="primary"),
273
+ UI.CancelAction(children="Cancel"),
274
+ ],
275
+ )
276
+ ```
277
+
278
+ **Parameters:**
279
+ - `uri` (required): Unique URI for the resource (e.g., `"ui://my-app/create-form"`)
280
+ - `name` (required): Name of the resource
281
+ - `description` (optional): Description of the resource
282
+ - `mime_type` (optional): MIME type of the content. Auto-set to `"application/vnd.opal.proteus+json"` when returning a `UI.Document`
283
+ - `title` (optional): Human-readable title
284
+
285
+ The handler function can return either a `str` (manual JSON serialization) or a `UI.Document` (automatic serialization with MIME type set automatically).
286
+
287
+ ### Linking a Tool to a UI Resource
288
+
289
+ Use the `ui_resource` parameter on `@tool` to associate a tool with a Proteus UI resource. The frontend fetches and renders the resource when the tool is invoked:
290
+
291
+ ```python
292
+ from opal_tools_sdk import tool
293
+ from pydantic import BaseModel, Field
294
+
295
+ class CreateItemParams(BaseModel):
296
+ item_name: str = Field(description="Name of the item")
297
+ description: str = Field(description="Item description")
298
+
299
+ @tool(
300
+ "create_item",
301
+ "Create a new item",
302
+ ui_resource="ui://my-app/create-form",
303
+ )
304
+ async def create_item(parameters: CreateItemParams):
305
+ return {"id": "item-123", "name": parameters.item_name, "status": "created"}
306
+ ```
307
+
308
+ ### Building UI with `UI.Document`
309
+
310
+ Import the `UI` namespace from `opal_tools_sdk` or `opal_tools_sdk.ui`. It provides type-safe builders for all Proteus components:
311
+
312
+ ```python
313
+ from opal_tools_sdk import UI
314
+ ```
315
+
316
+ **Available components:**
317
+
318
+ | Category | Components |
319
+ |----------|-----------|
320
+ | Layout | `UI.Document`, `UI.Group`, `UI.Card`, `UI.CardHeader`, `UI.CardLink`, `UI.Separator` |
321
+ | Typography | `UI.Heading`, `UI.Text`, `UI.Link` |
322
+ | Data Display | `UI.Avatar`, `UI.Badge`, `UI.DataTable`, `UI.Chart`, `UI.IconCalendar`, `UI.Image`, `UI.ImageCarousel`, `UI.Time` |
323
+ | Form Controls | `UI.Field`, `UI.Input`, `UI.Textarea`, `UI.Select`, `UI.SelectTrigger`, `UI.SelectContent`, `UI.Switch`, `UI.Range`, `UI.Question` |
324
+ | Actions | `UI.Action`, `UI.CancelAction` |
325
+ | Dynamic | `UI.Value`, `UI.Map`, `UI.MapIndex`, `UI.Show`, `UI.Concat`, `UI.Zip` |
326
+
327
+ **Data binding** with `UI.Value` resolves paths from the tool response:
328
+
329
+ ```python
330
+ @resource(uri="ui://my-app/results", name="results")
331
+ async def get_results():
332
+ return UI.Document(
333
+ title=UI.Value(path="/title"),
334
+ body=UI.Map(
335
+ path="/items",
336
+ children=UI.Text(children=UI.Value(path="name")),
337
+ ),
338
+ )
339
+ ```
340
+
341
+ **Conditional rendering** with `UI.Show`:
342
+
343
+ ```python
344
+ UI.Show(
345
+ when={"!!": UI.Value(path="/error")},
346
+ children=UI.Text(children="An error occurred", color="fg.error"),
347
+ )
348
+ ```
349
+
350
+ The MIME type constant is available as `UI.MIME_TYPE` (`"application/vnd.opal.proteus+json"`).
351
+
238
352
  ## Type Definitions
239
353
 
240
354
  The SDK provides several TypedDict and dataclass definitions for better type safety:
@@ -207,6 +207,120 @@ The response wrapper for islands:
207
207
  - Use `IslandResponse.create([islands])` to create responses
208
208
  - Supports multiple islands per response
209
209
 
210
+ ## Resources & Proteus UI
211
+
212
+ The SDK supports defining MCP resources that serve dynamic UI specifications using the Proteus framework. This enables tools to render rich, interactive interfaces without hardcoded frontend integrations.
213
+
214
+ For the full Proteus component reference and visual designer, see the [Proteus documentation](https://optimizely-axiom.github.io/optiaxiom/guides/proteus/).
215
+
216
+ ### Defining a Resource with `@resource`
217
+
218
+ Use the `@resource` decorator to register a function as an MCP resource:
219
+
220
+ ```python
221
+ from opal_tools_sdk import UI
222
+ from opal_tools_sdk.decorators import resource
223
+
224
+ @resource(
225
+ uri="ui://my-app/create-form",
226
+ name="create-form",
227
+ description="Form for creating new items",
228
+ )
229
+ async def get_create_form():
230
+ return UI.Document(
231
+ title="Create Item",
232
+ body=[
233
+ UI.Heading(children="New Item"),
234
+ UI.Field(
235
+ label="Item Name",
236
+ children=UI.Input(name="item_name", placeholder="Enter item name"),
237
+ ),
238
+ UI.Field(
239
+ label="Description",
240
+ children=UI.Textarea(name="description", placeholder="Enter description"),
241
+ ),
242
+ ],
243
+ actions=[
244
+ UI.Action(children="Save", appearance="primary"),
245
+ UI.CancelAction(children="Cancel"),
246
+ ],
247
+ )
248
+ ```
249
+
250
+ **Parameters:**
251
+ - `uri` (required): Unique URI for the resource (e.g., `"ui://my-app/create-form"`)
252
+ - `name` (required): Name of the resource
253
+ - `description` (optional): Description of the resource
254
+ - `mime_type` (optional): MIME type of the content. Auto-set to `"application/vnd.opal.proteus+json"` when returning a `UI.Document`
255
+ - `title` (optional): Human-readable title
256
+
257
+ The handler function can return either a `str` (manual JSON serialization) or a `UI.Document` (automatic serialization with MIME type set automatically).
258
+
259
+ ### Linking a Tool to a UI Resource
260
+
261
+ Use the `ui_resource` parameter on `@tool` to associate a tool with a Proteus UI resource. The frontend fetches and renders the resource when the tool is invoked:
262
+
263
+ ```python
264
+ from opal_tools_sdk import tool
265
+ from pydantic import BaseModel, Field
266
+
267
+ class CreateItemParams(BaseModel):
268
+ item_name: str = Field(description="Name of the item")
269
+ description: str = Field(description="Item description")
270
+
271
+ @tool(
272
+ "create_item",
273
+ "Create a new item",
274
+ ui_resource="ui://my-app/create-form",
275
+ )
276
+ async def create_item(parameters: CreateItemParams):
277
+ return {"id": "item-123", "name": parameters.item_name, "status": "created"}
278
+ ```
279
+
280
+ ### Building UI with `UI.Document`
281
+
282
+ Import the `UI` namespace from `opal_tools_sdk` or `opal_tools_sdk.ui`. It provides type-safe builders for all Proteus components:
283
+
284
+ ```python
285
+ from opal_tools_sdk import UI
286
+ ```
287
+
288
+ **Available components:**
289
+
290
+ | Category | Components |
291
+ |----------|-----------|
292
+ | Layout | `UI.Document`, `UI.Group`, `UI.Card`, `UI.CardHeader`, `UI.CardLink`, `UI.Separator` |
293
+ | Typography | `UI.Heading`, `UI.Text`, `UI.Link` |
294
+ | Data Display | `UI.Avatar`, `UI.Badge`, `UI.DataTable`, `UI.Chart`, `UI.IconCalendar`, `UI.Image`, `UI.ImageCarousel`, `UI.Time` |
295
+ | Form Controls | `UI.Field`, `UI.Input`, `UI.Textarea`, `UI.Select`, `UI.SelectTrigger`, `UI.SelectContent`, `UI.Switch`, `UI.Range`, `UI.Question` |
296
+ | Actions | `UI.Action`, `UI.CancelAction` |
297
+ | Dynamic | `UI.Value`, `UI.Map`, `UI.MapIndex`, `UI.Show`, `UI.Concat`, `UI.Zip` |
298
+
299
+ **Data binding** with `UI.Value` resolves paths from the tool response:
300
+
301
+ ```python
302
+ @resource(uri="ui://my-app/results", name="results")
303
+ async def get_results():
304
+ return UI.Document(
305
+ title=UI.Value(path="/title"),
306
+ body=UI.Map(
307
+ path="/items",
308
+ children=UI.Text(children=UI.Value(path="name")),
309
+ ),
310
+ )
311
+ ```
312
+
313
+ **Conditional rendering** with `UI.Show`:
314
+
315
+ ```python
316
+ UI.Show(
317
+ when={"!!": UI.Value(path="/error")},
318
+ children=UI.Text(children="An error occurred", color="fg.error"),
319
+ )
320
+ ```
321
+
322
+ The MIME type constant is available as `UI.MIME_TYPE` (`"application/vnd.opal.proteus+json"`).
323
+
210
324
  ## Type Definitions
211
325
 
212
326
  The SDK provides several TypedDict and dataclass definitions for better type safety:
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: proteus-document-spec.json
3
- # timestamp: 2026-04-20T19:00:23+00:00
3
+ # timestamp: 2026-04-27T14:20:49+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -22,6 +22,9 @@ class ProteusEventHandler1(BaseModel):
22
22
  extra='forbid',
23
23
  )
24
24
  interaction: str = Field(..., description='Name of registered interaction to call')
25
+ params: dict[str, Any] | None = Field(
26
+ default=None, description='Parameters to pass to the interaction handler'
27
+ )
25
28
 
26
29
 
27
30
  class Series(BaseModel):
@@ -592,6 +595,22 @@ class ProteusBadge(BaseModel):
592
595
  z: SprinklePropZ | None = None
593
596
 
594
597
 
598
+ class ProteusBridge(BaseModel):
599
+ model_config = ConfigDict(
600
+ extra='forbid',
601
+ )
602
+ field_type: Literal['Bridge'] = Field(default='Bridge', alias='$type')
603
+ fallback: ProteusNode | None = Field(
604
+ default=None,
605
+ description="Content rendered on platforms without iframe support (Teams, Slack, mobile). If omitted, a default 'View in Opal web' message is shown.",
606
+ )
607
+ height: float | None = Field(default=None, description='Height of the iframe in pixels')
608
+ resource: str = Field(
609
+ ...,
610
+ description="Resource URI identifying the MCP app to render (e.g., 'ui://sample-widget')",
611
+ )
612
+
613
+
595
614
  class ProteusButton(BaseModel):
596
615
  model_config = ConfigDict(
597
616
  extra='forbid',
@@ -922,7 +941,7 @@ class ProteusDataTable(BaseModel):
922
941
  extra='forbid',
923
942
  )
924
943
  field_type: Literal['DataTable'] = Field(default='DataTable', alias='$type')
925
- columns: list[Column] | None = Field(default=None, description='Column definitions')
944
+ columns: list[Column] | ProteusExpression | None = None
926
945
  data: list[dict[str, Any]] | ProteusExpression | ProteusZip | None = None
927
946
 
928
947
 
@@ -2170,6 +2189,7 @@ class ProteusElement(
2170
2189
  ProteusAction
2171
2190
  | ProteusAvatar
2172
2191
  | ProteusBadge
2192
+ | ProteusBridge
2173
2193
  | ProteusButton
2174
2194
  | ProteusCard
2175
2195
  | ProteusCardHeader
@@ -2205,6 +2225,7 @@ class ProteusElement(
2205
2225
  ProteusAction
2206
2226
  | ProteusAvatar
2207
2227
  | ProteusBadge
2228
+ | ProteusBridge
2208
2229
  | ProteusButton
2209
2230
  | ProteusCard
2210
2231
  | ProteusCardHeader
@@ -3881,6 +3902,7 @@ ProteusZip.model_rebuild()
3881
3902
  ProteusAction.model_rebuild()
3882
3903
  ProteusAvatar.model_rebuild()
3883
3904
  ProteusBadge.model_rebuild()
3905
+ ProteusBridge.model_rebuild()
3884
3906
  ProteusButton.model_rebuild()
3885
3907
  ProteusCard.model_rebuild()
3886
3908
  ProteusCardHeader.model_rebuild()
@@ -3925,6 +3947,7 @@ class UI:
3925
3947
  Action = ProteusAction
3926
3948
  Avatar = ProteusAvatar
3927
3949
  Badge = ProteusBadge
3950
+ Bridge = ProteusBridge
3928
3951
  Button = ProteusButton
3929
3952
  Card = ProteusCard
3930
3953
  CardHeader = ProteusCardHeader
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: optimizely-opal.opal-tools-sdk
3
- Version: 0.1.27.dev0
3
+ Version: 0.1.28.dev0
4
4
  Summary: SDK for creating Opal-compatible tools services
5
5
  Home-page: https://github.com/optimizely/opal-tools-sdk
6
6
  Author: Optimizely
@@ -235,6 +235,120 @@ The response wrapper for islands:
235
235
  - Use `IslandResponse.create([islands])` to create responses
236
236
  - Supports multiple islands per response
237
237
 
238
+ ## Resources & Proteus UI
239
+
240
+ The SDK supports defining MCP resources that serve dynamic UI specifications using the Proteus framework. This enables tools to render rich, interactive interfaces without hardcoded frontend integrations.
241
+
242
+ For the full Proteus component reference and visual designer, see the [Proteus documentation](https://optimizely-axiom.github.io/optiaxiom/guides/proteus/).
243
+
244
+ ### Defining a Resource with `@resource`
245
+
246
+ Use the `@resource` decorator to register a function as an MCP resource:
247
+
248
+ ```python
249
+ from opal_tools_sdk import UI
250
+ from opal_tools_sdk.decorators import resource
251
+
252
+ @resource(
253
+ uri="ui://my-app/create-form",
254
+ name="create-form",
255
+ description="Form for creating new items",
256
+ )
257
+ async def get_create_form():
258
+ return UI.Document(
259
+ title="Create Item",
260
+ body=[
261
+ UI.Heading(children="New Item"),
262
+ UI.Field(
263
+ label="Item Name",
264
+ children=UI.Input(name="item_name", placeholder="Enter item name"),
265
+ ),
266
+ UI.Field(
267
+ label="Description",
268
+ children=UI.Textarea(name="description", placeholder="Enter description"),
269
+ ),
270
+ ],
271
+ actions=[
272
+ UI.Action(children="Save", appearance="primary"),
273
+ UI.CancelAction(children="Cancel"),
274
+ ],
275
+ )
276
+ ```
277
+
278
+ **Parameters:**
279
+ - `uri` (required): Unique URI for the resource (e.g., `"ui://my-app/create-form"`)
280
+ - `name` (required): Name of the resource
281
+ - `description` (optional): Description of the resource
282
+ - `mime_type` (optional): MIME type of the content. Auto-set to `"application/vnd.opal.proteus+json"` when returning a `UI.Document`
283
+ - `title` (optional): Human-readable title
284
+
285
+ The handler function can return either a `str` (manual JSON serialization) or a `UI.Document` (automatic serialization with MIME type set automatically).
286
+
287
+ ### Linking a Tool to a UI Resource
288
+
289
+ Use the `ui_resource` parameter on `@tool` to associate a tool with a Proteus UI resource. The frontend fetches and renders the resource when the tool is invoked:
290
+
291
+ ```python
292
+ from opal_tools_sdk import tool
293
+ from pydantic import BaseModel, Field
294
+
295
+ class CreateItemParams(BaseModel):
296
+ item_name: str = Field(description="Name of the item")
297
+ description: str = Field(description="Item description")
298
+
299
+ @tool(
300
+ "create_item",
301
+ "Create a new item",
302
+ ui_resource="ui://my-app/create-form",
303
+ )
304
+ async def create_item(parameters: CreateItemParams):
305
+ return {"id": "item-123", "name": parameters.item_name, "status": "created"}
306
+ ```
307
+
308
+ ### Building UI with `UI.Document`
309
+
310
+ Import the `UI` namespace from `opal_tools_sdk` or `opal_tools_sdk.ui`. It provides type-safe builders for all Proteus components:
311
+
312
+ ```python
313
+ from opal_tools_sdk import UI
314
+ ```
315
+
316
+ **Available components:**
317
+
318
+ | Category | Components |
319
+ |----------|-----------|
320
+ | Layout | `UI.Document`, `UI.Group`, `UI.Card`, `UI.CardHeader`, `UI.CardLink`, `UI.Separator` |
321
+ | Typography | `UI.Heading`, `UI.Text`, `UI.Link` |
322
+ | Data Display | `UI.Avatar`, `UI.Badge`, `UI.DataTable`, `UI.Chart`, `UI.IconCalendar`, `UI.Image`, `UI.ImageCarousel`, `UI.Time` |
323
+ | Form Controls | `UI.Field`, `UI.Input`, `UI.Textarea`, `UI.Select`, `UI.SelectTrigger`, `UI.SelectContent`, `UI.Switch`, `UI.Range`, `UI.Question` |
324
+ | Actions | `UI.Action`, `UI.CancelAction` |
325
+ | Dynamic | `UI.Value`, `UI.Map`, `UI.MapIndex`, `UI.Show`, `UI.Concat`, `UI.Zip` |
326
+
327
+ **Data binding** with `UI.Value` resolves paths from the tool response:
328
+
329
+ ```python
330
+ @resource(uri="ui://my-app/results", name="results")
331
+ async def get_results():
332
+ return UI.Document(
333
+ title=UI.Value(path="/title"),
334
+ body=UI.Map(
335
+ path="/items",
336
+ children=UI.Text(children=UI.Value(path="name")),
337
+ ),
338
+ )
339
+ ```
340
+
341
+ **Conditional rendering** with `UI.Show`:
342
+
343
+ ```python
344
+ UI.Show(
345
+ when={"!!": UI.Value(path="/error")},
346
+ children=UI.Text(children="An error occurred", color="fg.error"),
347
+ )
348
+ ```
349
+
350
+ The MIME type constant is available as `UI.MIME_TYPE` (`"application/vnd.opal.proteus+json"`).
351
+
238
352
  ## Type Definitions
239
353
 
240
354
  The SDK provides several TypedDict and dataclass definitions for better type safety:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "optimizely-opal.opal-tools-sdk"
7
- version = "0.1.27-dev"
7
+ version = "0.1.28-dev"
8
8
  description = "SDK for creating Opal-compatible tools services"
9
9
  authors = [{ name = "Optimizely", email = "opal-team@optimizely.com" }]
10
10
  readme = "README.md"
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="optimizely-opal.opal-tools-sdk",
5
- version="0.1.27-dev",
5
+ version="0.1.28-dev",
6
6
  packages=find_packages(),
7
7
  install_requires=[
8
8
  "fastapi>=0.100.0",