pyegeria 5.4.5__py3-none-any.whl → 5.4.7__py3-none-any.whl
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.
- commands/cat/dr_egeria_command_help.py +0 -0
- commands/cat/exp_list_glossaries.py +0 -0
- commands/cat/get_collection.py +0 -0
- commands/cat/get_project_dependencies.py +0 -0
- commands/cat/get_project_structure.py +0 -0
- commands/cat/list_assets.py +0 -0
- commands/cat/list_cert_types.py +0 -0
- commands/cat/list_collections.py +0 -0
- commands/cat/list_data_designer.py +0 -0
- commands/cat/list_data_structures_full.py +0 -0
- commands/cat/list_deployed_servers.py +0 -0
- commands/cat/list_glossaries.py +0 -0
- commands/cat/list_projects.py +0 -0
- commands/cat/list_tech_types.py +0 -0
- commands/cat/list_terms.py +0 -0
- commands/cat/list_todos.py +0 -0
- commands/cli/egeria.py +0 -0
- commands/my/list_my_profile.py +0 -0
- commands/my/list_my_roles.py +0 -0
- commands/my/monitor_my_todos.py +0 -0
- commands/my/monitor_open_todos.py +0 -0
- commands/ops/list_archives.py +0 -0
- commands/ops/list_catalog_targets.py +0 -0
- commands/ops/monitor_asset_events.py +0 -0
- commands/ops/monitor_engine_activity.py +0 -0
- commands/ops/monitor_engine_activity_c.py +0 -0
- commands/ops/monitor_gov_eng_status.py +0 -0
- commands/ops/monitor_integ_daemon_status.py +0 -0
- commands/ops/monitor_platform_status.py +0 -0
- commands/ops/monitor_server_startup.py +0 -0
- commands/ops/monitor_server_status.py +0 -0
- commands/ops/orig_monitor_server_list.py +0 -0
- commands/ops/orig_monitor_server_status.py +0 -0
- commands/ops/table_integ_daemon_status.py +0 -0
- commands/tech/get_guid_info.py +0 -0
- commands/tech/get_tech_details.py +0 -0
- commands/tech/list_anchored_elements.py +0 -0
- commands/tech/list_asset_types.py +0 -0
- commands/tech/list_gov_action_processes.py +0 -0
- commands/tech/list_information_supply_chains.py +0 -0
- commands/tech/list_registered_services.py +0 -0
- commands/tech/list_relationship_types.py +0 -0
- commands/tech/list_relationships.py +0 -0
- commands/tech/list_solution_blueprints.py +0 -0
- commands/tech/list_solution_components.py +0 -0
- commands/tech/list_solution_roles.py +0 -0
- commands/tech/list_valid_metadata_values.py +0 -0
- md_processing/__init__.py +2 -0
- md_processing/dr_egeria.py +5 -2
- md_processing/md_commands/data_designer_commands.py +6 -1
- md_processing/md_commands/product_manager_commands.py +101 -1
- md_processing/md_processing_utils/md_processing_constants.py +2 -1
- pyegeria/__init__.py +1 -0
- pyegeria/_client_new.py +1 -1
- pyegeria/_output_formats.py +43 -7
- pyegeria/automated_curation.py +122 -15
- pyegeria/data_designer.py +3 -3
- pyegeria/format_set_executor.py +159 -0
- pyegeria/mcp_adapter.py +110 -0
- pyegeria/mcp_server.py +172 -0
- pyegeria/project_manager.py +1 -1
- pyegeria/reference_data.py +1 -1
- pyegeria/x_action_author_omvs.py +1 -1
- {pyegeria-5.4.5.dist-info → pyegeria-5.4.7.dist-info}/METADATA +26 -29
- pyegeria-5.4.7.dist-info/RECORD +174 -0
- {pyegeria-5.4.5.dist-info → pyegeria-5.4.7.dist-info}/WHEEL +2 -1
- pyegeria-5.4.7.dist-info/entry_points.txt +105 -0
- pyegeria-5.4.7.dist-info/top_level.txt +3 -0
- commands/README.md +0 -47
- commands/cat/README.md +0 -16
- commands/cat/debug_log.2025-09-14_11-03-29_316193.log.zip +0 -0
- commands/cat/debug_log.2025-09-15_19-06-37_086464.log.zip +0 -0
- commands/cat/debug_log.2025-09-20_11-10-54_418109.log.zip +0 -0
- commands/cat/debug_log.2025-09-21_11-59-27_391328.log.zip +0 -0
- commands/cli/debug_log +0 -0
- commands/cli/txt_custom_v2.tcss +0 -19
- commands/doc/README.md +0 -145
- commands/doc/Visual Command Reference/README.md +0 -511
- commands/doc/Visual Command Reference/cat/show/assets/asset-graph 2024-11-20 at 15.56.42.png +0 -0
- commands/doc/Visual Command Reference/cat/show/assets/assets-in-domain 2024-11-20 at 15.49.55@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/assets/elements-of-type 2024-11-20 at 16.01.35.png +0 -0
- commands/doc/Visual Command Reference/cat/show/assets/tech-type-elements 2024-11-20 at 16.05.05.png +0 -0
- commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-data-catalogs 2024-12-17 at 15.43.27@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-data-catalogs-2024-11-20 at 16.17.43@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-schemas 2024-11-25 at 20.14.50@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-schemas 2024-12-17 at 15.48.38@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-servers 2024-11-25 at 20.21.25@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-servers 2024-12-17 at 15.52.16@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/deployed-data/deployed_databases 2024-12-16 at 16.40.31@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/glossary/list-glossaries 2024-11-25 at 20.30.02.png +0 -0
- commands/doc/Visual Command Reference/cat/show/glossary/list-terms 2024-11-25 at 20.32.11.png +0 -0
- commands/doc/Visual Command Reference/cat/show/info/asset-types 2024-11-25 at 20.34.19@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/info/certification-types 2024-11-25 at 20.37.07.png +0 -0
- commands/doc/Visual Command Reference/cat/show/info/collection-graph 2024-12-12 at 11.33.18@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/info/list-collections 2024-12-10 at 14.25.51@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/info/list-todos 2024-12-12 at 11.46.30@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/info/list-user-ids 2024-12-12 at 11.51.09@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/info/tech-types 2024-12-12 at 11.37.20@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/projects/project_dependencies 2024-12-14 at 16.24.39@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/projects/project_structure 2024-12-14 at 16.21.35@2x.png +0 -0
- commands/doc/Visual Command Reference/cat/show/projects/projects 2024-12-14 at 16.18.10@2x.png +0 -0
- commands/doc/Visual Command Reference/hey_egeria tui 2024-12-16 at 16.58.22@2x.png +0 -0
- commands/doc/Visual Command Reference/my/show/my_profile 2024-12-14 at 16.29.27@2x.png +0 -0
- commands/doc/Visual Command Reference/my/show/my_roles 2024-12-14 at 16.32.10@2x.png +0 -0
- commands/doc/Visual Command Reference/my/show/my_todos 2024-12-15 at 16.24.13@2x.png +0 -0
- commands/doc/Visual Command Reference/my/show/open_todos 2024-12-14 at 16.36.12@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/engines/list_engine_activity compressed 2024-12-15 at 16.48.48@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/engines/monitor_engine_activity 2024-12-15 at 16.32.55@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/engines/monitor_engine_activity compressed 2024-12-15 at 16.38.29@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/engines/monitor_engine_status 2024-12-15 at 16.51.26.jpeg +0 -0
- commands/doc/Visual Command Reference/ops/show/integrations/monitor_integration_daemon_status 2024-12-15 at 16.57.12@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/integrations/monitor_integration_targets 2024-12-15 at 17.02.19@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/platforms/monitor_platform_status 2024-12-15 at 19.53.18@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/servers/monitor_server_status 2024-12-15 at 19.59.39@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/servers/monitor_server_status full 2024-12-15 at 20.01.57@2x.png +0 -0
- commands/doc/Visual Command Reference/ops/show/servers/monitor_startup_servers 2024-12-15 at 19.56.07@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/get_anchored_elements 2024-12-15 at 21.25.41@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/get_elements_of_om_type 2024-12-16 at 14.39.59@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/info_for_guid 2024-12-16 at 11.35.29@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/list_elements_by_om-type 2024-12-16 at 14.24.18@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/list_elements_by_om-type extended 2024-12-16 at 14.28.46@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/list_elements_of_om_type_by_classification 2024-12-16 at 14.35.26@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/related_elements 2024-12-16 at 14.55.01@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/elements/show_related_specifications 2024-12-16 at 15.04.55@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-info/asset_types 2024-12-16 at 15.10.16@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-info/detailed_governance_action_processes 2024-12-16 at 15.16.26@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-info/governance_action_processes 2024-12-16 at 15.13.01@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-info/registered_services 2024-12-16 at 16.44.54@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-info/relationship_types 2024-12-16 at 16.20.34@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-info/relationship_types 2024-12-19 at 10.51.54@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-info/valid_metadata_values 2024-12-16 at 15.31.56@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-types/list_tech_type_template_specs 2024-12-16 at 16.03.22@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-types/list_technology_types 2024-12-16 at 15.39.20@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-types/tech_type_details 2024-12-16 at 15.37.21@2x.png +0 -0
- commands/doc/Visual Command Reference/tech/show/tech-types/tech_type_templates 2024-12-16 at 16.11.48@2x.png +0 -0
- commands/doc/glossary/basic-glossary-tui.md +0 -109
- commands/doc/glossary/images/delete-glossary-step1 2024-11-06 at 15.47.23@2x.png +0 -0
- commands/doc/glossary/images/delete-glossary-step2 2024-11-06 at 15.51.29@2x.png +0 -0
- commands/doc/glossary/images/delete-glossary-step3 2024-11-06 at 15.53.19@2x.png +0 -0
- commands/doc/glossary/images/delete-glossary-step4 2024-11-06 at 15.55.11@2x.png +0 -0
- commands/doc/glossary/images/out-create-glossary example 2024-11-05 at 20.38.04@2x.png +0 -0
- commands/doc/glossary/images/out-create-term 2024-11-06 at 20.48.29.png +0 -0
- commands/doc/glossary/images/out-delete-term 2024-11-07 at 03.57.25.png +0 -0
- commands/doc/glossary/images/out-display-terms-for-glossary-test 2024-11-06 at 20.51.28.png +0 -0
- commands/doc/glossary/images/out-export-example 2024-11-07 at 09.54.57.png +0 -0
- commands/doc/glossary/images/out-exported-terms 2024-11-06 at 21.06.32.png +0 -0
- commands/doc/glossary/images/out-glossary-list example 2024-11-05 at 20.41.02@2x.png +0 -0
- commands/doc/glossary/images/out-import-terms 2024-11-07 at 08.15.18.png +0 -0
- commands/doc/glossary/images/out-list-all-terms 2024-11-06 at 16.22.20@2x.png +0 -0
- commands/doc/glossary/images/out-list-terms-for-example 2024-11-06 at 16.40.12.png +0 -0
- commands/doc/glossary/images/out-list-terms-second 2024-11-06 at 16.45.13.png +0 -0
- commands/doc/glossary/images/out-pipx install pyegeria 2024-11-10 at 18.12.21.png +0 -0
- commands/doc/glossary/images/out-server-status-full 2024-11-10 at 18.25.14.png +0 -0
- commands/doc/glossary/images/out-servers-status 2024-11-10 at 18.15.42.png +0 -0
- commands/doc/glossary/images/out-upsert-import 2024-11-07 at 19.37.00.png +0 -0
- commands/doc/glossary/images/tui-2024-11-10 at 18.26.29.png +0 -0
- commands/doc/glossary/images/tui-create-glossary example 2024-11-05 at 20.34.24@2x.png +0 -0
- commands/doc/glossary/images/tui-create-term 2024-11-06 at 20.46.35.png +0 -0
- commands/doc/glossary/images/tui-delete-term 2024-11-07 at 03.51.57.png +0 -0
- commands/doc/glossary/images/tui-display-terms-for-example 2024-11-06 at 20.56.49.png +0 -0
- commands/doc/glossary/images/tui-export-example 2024-11-07 at 09.52.59.png +0 -0
- commands/doc/glossary/images/tui-hey-egeria 2024-11-10 at 18.31.01.png +0 -0
- commands/doc/glossary/images/tui-import-upsert-example 2024-11-07 at 10.08.37.png +0 -0
- commands/doc/glossary/images/tui-list-terms-second 2024-11-06 at 16.46.34.png +0 -0
- commands/doc/glossary/images/tui-load-archive.png +0 -0
- commands/doc/glossary/images/tui-server-status-full 2024-11-10 at 19.14.36.png +0 -0
- commands/doc/glossary/images/tui-show-glossaries 2024-11-07 at 20.00.05.png +0 -0
- commands/doc/glossary/images/tui-show-glossary-terms 2024-11-05 at 19.37.53@2x.png +0 -0
- commands/doc/glossary/images/tui-upsert 2024-11-07 at 11.49.04.png +0 -0
- commands/doc/glossary/images/upsert-example.om-terms 2024-11-07 at 11.44.05.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/README.md +0 -346
- commands/doc/hey_egeria: a pyegeria command line interface/images/CleanShot 2024-11-18 at 21.32.03@2x.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/Xmind 1731421782704.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/Xmind 1731422134920.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/hey_egeria 2024-11-12 at 20.38.43.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/hey_egeria cat 2024-11-12 at 21.41.43.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/out-integ-status-list 2024-11-12 at 16.45.26.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/out-integ-status-live 2024-11-12 at 16.44.12@2x.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/out-server-status 2024-11-10 at 18.15.42@2x.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/out-server-status-full 2024-11-10 at 18.25.14@2x.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/short-cut commands 2024-11-12 at 22.22.13.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/tui-hey-egeria.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/tui-integration-status-paging.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/tui-load-archive 2024-11-10 at 19.19.09@2x.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/tui-show-server-status 2024-11-10 at 18.52.01@2x.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/tui-show-server-status-full 2024-11-10.png +0 -0
- commands/doc/hey_egeria: a pyegeria command line interface/images/tui-status-paging 2024-11-12 at 16.26.14@2x.png +0 -0
- commands/my/README.md +0 -17
- commands/ops/README.md +0 -24
- commands/tech/README.md +0 -24
- md_processing/.obsidian/app.json +0 -1
- md_processing/.obsidian/appearance.json +0 -1
- md_processing/.obsidian/community-plugins.json +0 -1
- md_processing/.obsidian/core-plugins.json +0 -33
- md_processing/.obsidian/workspace.json +0 -167
- md_processing/data/commands-working.json +0 -34850
- md_processing/data/commands.json +0 -51697
- md_processing/data/generated_format_sets.json +0 -4137
- md_processing/dr_egeria_inbox/glossary_creation_experiment.ipynb +0 -341
- md_processing/md_processing_utils/debug_log +0 -84
- md_processing/md_processing_utils/dr-egeria-help-2025-09-09T11:10:03.md +0 -3305
- md_processing/md_processing_utils/dr-egeria-help-2025-09-10T14:49:49.md +0 -3460
- md_processing/md_processing_utils/dr-egeria-help-2025-09-10T14:57:46.md +0 -472
- pyegeria/README.md +0 -35
- pyegeria-5.4.5.dist-info/RECORD +0 -306
- pyegeria-5.4.5.dist-info/entry_points.txt +0 -105
- {pyegeria-5.4.5.dist-info → pyegeria-5.4.7.dist-info/licenses}/LICENSE +0 -0
pyegeria/data_designer.py
CHANGED
@@ -280,7 +280,7 @@ class DataDesigner(Client2):
|
|
280
280
|
|
281
281
|
"""
|
282
282
|
url = f"{self.data_designer_root}/data-structures/from-template"
|
283
|
-
return await self.
|
283
|
+
return await self._async_create_element_from_template(url, body)
|
284
284
|
|
285
285
|
@dynamic_catch
|
286
286
|
def create_data_structure_from_template(self, body: dict | TemplateRequestBody) -> str:
|
@@ -1696,7 +1696,7 @@ class DataDesigner(Client2):
|
|
1696
1696
|
|
1697
1697
|
url = f"{base_path(self, self.view_server)}/data-fields/from-template"
|
1698
1698
|
|
1699
|
-
return await self.
|
1699
|
+
return await self._async_create_element_from_template(url, body)
|
1700
1700
|
|
1701
1701
|
@dynamic_catch
|
1702
1702
|
def create_data_field_from_template(self, body: dict | TemplateRequestBody) -> str:
|
@@ -2945,7 +2945,7 @@ class DataDesigner(Client2):
|
|
2945
2945
|
"""
|
2946
2946
|
|
2947
2947
|
url = f"{base_path(self, self.view_server)}/data-classes/from-template"
|
2948
|
-
return await self.
|
2948
|
+
return await self._async_create_element_from_template(url, body)
|
2949
2949
|
|
2950
2950
|
@dynamic_catch
|
2951
2951
|
def create_data_class_from_template(self, body: dict | TemplateRequestBody) -> str:
|
@@ -0,0 +1,159 @@
|
|
1
|
+
"""
|
2
|
+
SPDX-License-Identifier: Apache-2.0
|
3
|
+
Copyright Contributors to the ODPi Egeria project.
|
4
|
+
|
5
|
+
A pure helper to execute a FormatSet action and return normalized results without side effects
|
6
|
+
(printing or writing to disk). This is suitable for programmatic use (e.g., MCP adapters,
|
7
|
+
notebooks, services) that want DICT/JSON or text output directly.
|
8
|
+
|
9
|
+
Notes
|
10
|
+
- Only use this for read-style format sets. It assumes the action is safe to call.
|
11
|
+
- Credentials and endpoints default from pyegeria.config.settings (ENV/config.json/ENV files).
|
12
|
+
- Prefer output_format="DICT" for machine-consumable results. REPORT/HTML/MERMAID are returned as text.
|
13
|
+
"""
|
14
|
+
from __future__ import annotations
|
15
|
+
|
16
|
+
import json
|
17
|
+
from typing import Any, Dict, Optional
|
18
|
+
|
19
|
+
from loguru import logger
|
20
|
+
|
21
|
+
from pyegeria import (
|
22
|
+
EgeriaTech,
|
23
|
+
CollectionManager,
|
24
|
+
GovernanceOfficer,
|
25
|
+
GlossaryManager,
|
26
|
+
NO_ELEMENTS_FOUND,
|
27
|
+
)
|
28
|
+
from pyegeria.config import settings
|
29
|
+
from pyegeria.external_references import ExternalReferences
|
30
|
+
from pyegeria._exceptions_new import PyegeriaException
|
31
|
+
from pyegeria._output_formats import (
|
32
|
+
select_output_format_set,
|
33
|
+
get_output_format_set_heading,
|
34
|
+
get_output_format_set_description,
|
35
|
+
)
|
36
|
+
|
37
|
+
|
38
|
+
_CLIENT_CLASS_MAP = {
|
39
|
+
"CollectionManager": CollectionManager,
|
40
|
+
"GovernanceOfficer": GovernanceOfficer,
|
41
|
+
"GlossaryManager": GlossaryManager,
|
42
|
+
"ExternalReference": ExternalReferences,
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
def _resolve_client_and_method(func_decl: str):
|
47
|
+
"""Given a function declaration like 'ClassName.method', return (client_class, method_name)."""
|
48
|
+
if not isinstance(func_decl, str) or "." not in func_decl:
|
49
|
+
return (EgeriaTech, None)
|
50
|
+
class_name, method_name = func_decl.split(".", 1)
|
51
|
+
client_class = _CLIENT_CLASS_MAP.get(class_name, EgeriaTech)
|
52
|
+
return (client_class, method_name)
|
53
|
+
|
54
|
+
|
55
|
+
def run_format_set_action_return(
|
56
|
+
format_set_name: str,
|
57
|
+
*,
|
58
|
+
output_format: str = "DICT",
|
59
|
+
params: Optional[Dict[str, Any]] = None,
|
60
|
+
view_server: str = settings.Environment.egeria_view_server,
|
61
|
+
view_url: str = settings.Environment.egeria_view_server_url,
|
62
|
+
user: str = settings.User_Profile.user_name,
|
63
|
+
user_pass: str = settings.User_Profile.user_pwd,
|
64
|
+
) -> Dict[str, Any]:
|
65
|
+
"""
|
66
|
+
Execute the action for a given format set and return a normalized result structure.
|
67
|
+
|
68
|
+
Returns shapes:
|
69
|
+
- {"kind":"empty"}
|
70
|
+
- {"kind":"json","data": <list|dict|any>}
|
71
|
+
- {"kind":"text","mime": "text/markdown"|"text/html","content": str}
|
72
|
+
- {"kind":"unknown","raw": any}
|
73
|
+
"""
|
74
|
+
output_format = (output_format or "DICT").upper()
|
75
|
+
params = dict(params or {})
|
76
|
+
|
77
|
+
# Resolve the format set and action
|
78
|
+
fmt = select_output_format_set(format_set_name, output_format)
|
79
|
+
if not fmt:
|
80
|
+
raise ValueError(
|
81
|
+
f"Output format set '{format_set_name}' does not have a compatible '{output_format}' format."
|
82
|
+
)
|
83
|
+
if "action" not in fmt:
|
84
|
+
raise ValueError(f"Output format set '{format_set_name}' does not have an action property.")
|
85
|
+
|
86
|
+
action = fmt["action"]
|
87
|
+
func_decl = action.get("function")
|
88
|
+
required_params = action.get("required_params", action.get("user_params", [])) or []
|
89
|
+
optional_params = action.get("optional_params", []) or []
|
90
|
+
spec_params = action.get("spec_params", {}) or {}
|
91
|
+
|
92
|
+
# Build call params: required/optional provided by caller + fixed spec_params
|
93
|
+
call_params: Dict[str, Any] = {}
|
94
|
+
|
95
|
+
# Populate required and optional params when provided
|
96
|
+
for p in required_params:
|
97
|
+
if p in params and params[p] is not None:
|
98
|
+
call_params[p] = params[p]
|
99
|
+
elif p not in spec_params:
|
100
|
+
# Missing required param
|
101
|
+
logger.warning(f"Required parameter '{p}' not provided for format set '{format_set_name}'.")
|
102
|
+
for p in optional_params:
|
103
|
+
if p in params and params[p] is not None:
|
104
|
+
call_params[p] = params[p]
|
105
|
+
|
106
|
+
# Include fixed specifics
|
107
|
+
call_params.update(spec_params)
|
108
|
+
|
109
|
+
# Always include output_format and output_format_set for downstream rendering
|
110
|
+
call_params["output_format"] = output_format
|
111
|
+
call_params["output_format_set"] = format_set_name
|
112
|
+
|
113
|
+
client_class, method_name = _resolve_client_and_method(func_decl)
|
114
|
+
client = client_class(view_server, view_url, user_id=user, user_pwd=user_pass)
|
115
|
+
|
116
|
+
try:
|
117
|
+
client.create_egeria_bearer_token()
|
118
|
+
func = getattr(client, method_name) if method_name and hasattr(client, method_name) else None
|
119
|
+
if func is None:
|
120
|
+
raise AttributeError(
|
121
|
+
f"Method '{method_name}' not found in client class '{client_class.__name__}'."
|
122
|
+
)
|
123
|
+
|
124
|
+
result = func(**call_params)
|
125
|
+
|
126
|
+
if not result or result == NO_ELEMENTS_FOUND:
|
127
|
+
return {"kind": "empty"}
|
128
|
+
|
129
|
+
# Prepare optional preamble for narrative outputs
|
130
|
+
heading = get_output_format_set_heading(format_set_name)
|
131
|
+
desc = get_output_format_set_description(format_set_name)
|
132
|
+
preamble = f"# {heading}\n{desc}\n\n" if heading and desc else ""
|
133
|
+
|
134
|
+
if output_format in {"DICT", "JSON", "ALL"}:
|
135
|
+
# Return raw data (list/dict/any) — do not stringify here
|
136
|
+
return {"kind": "json", "data": result}
|
137
|
+
elif output_format in {"REPORT", "MERMAID"}:
|
138
|
+
content = result
|
139
|
+
if isinstance(result, (list, dict)):
|
140
|
+
# Make a simple JSON code block if the source returned structured data unexpectedly
|
141
|
+
content = preamble + "```json\n" + json.dumps(result, indent=2) + "\n```"
|
142
|
+
else:
|
143
|
+
content = preamble + str(result)
|
144
|
+
return {"kind": "text", "mime": "text/markdown", "content": content}
|
145
|
+
elif output_format == "HTML":
|
146
|
+
content = str(result)
|
147
|
+
return {"kind": "text", "mime": "text/html", "content": content}
|
148
|
+
else:
|
149
|
+
# Unknown or table-like formats which aren't appropriate for MCP by default
|
150
|
+
return {"kind": "unknown", "raw": result}
|
151
|
+
|
152
|
+
except PyegeriaException as e:
|
153
|
+
# Re-raise with a simpler message for upstream mapping
|
154
|
+
raise
|
155
|
+
finally:
|
156
|
+
try:
|
157
|
+
client.close_session()
|
158
|
+
except Exception:
|
159
|
+
pass
|
pyegeria/mcp_adapter.py
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
"""
|
2
|
+
SPDX-License-Identifier: Apache-2.0
|
3
|
+
|
4
|
+
Thin adapter helpers to surface pyegeria FormatSets as MCP-style tools without
|
5
|
+
side effects. This does NOT implement an MCP transport/server; it focuses on
|
6
|
+
programmatic functions that an MCP server entry point can call.
|
7
|
+
|
8
|
+
Only format sets that advertise DICT or ALL are considered eligible.
|
9
|
+
"""
|
10
|
+
from __future__ import annotations
|
11
|
+
|
12
|
+
import json
|
13
|
+
import sys
|
14
|
+
import asyncio
|
15
|
+
|
16
|
+
from loguru import logger
|
17
|
+
from typing import Any, Dict, Optional
|
18
|
+
|
19
|
+
from loguru import logger
|
20
|
+
|
21
|
+
from pyegeria._output_formats import (
|
22
|
+
list_mcp_format_sets,
|
23
|
+
select_output_format_set,
|
24
|
+
get_output_format_type_match,
|
25
|
+
)
|
26
|
+
from pyegeria.format_set_executor import run_format_set_action_return
|
27
|
+
|
28
|
+
|
29
|
+
def list_reports() -> dict:
|
30
|
+
"""List eligible format sets as MCP tools (support DICT or ALL)."""
|
31
|
+
return list_mcp_format_sets()
|
32
|
+
|
33
|
+
|
34
|
+
def describe_report(name: str, outputType: str = "DICT") -> Dict[str, Any]:
|
35
|
+
"""
|
36
|
+
Describe a format set for MCP discovery. If outputType != ANY, a concrete format
|
37
|
+
will be resolved; otherwise only metadata/action are returned.
|
38
|
+
"""
|
39
|
+
meta = select_output_format_set(name, outputType)
|
40
|
+
if not meta:
|
41
|
+
raise ValueError(f"Unknown or incompatible format set: {name}")
|
42
|
+
return meta
|
43
|
+
|
44
|
+
|
45
|
+
def _execute_egeria_call_blocking(
|
46
|
+
*,
|
47
|
+
report: str,
|
48
|
+
params: Optional[Dict[str, Any]] = None,
|
49
|
+
view_server: Optional[str] = None,
|
50
|
+
view_url: Optional[str] = None,
|
51
|
+
user: Optional[str] = None,
|
52
|
+
user_pass: Optional[str] = None,) -> Dict[str, Any]:
|
53
|
+
"""
|
54
|
+
Executes the synchronous, blocking Egeria client call on a dedicated worker thread.
|
55
|
+
|
56
|
+
You must replace the hardcoded return with your actual Egeria client logic here.
|
57
|
+
All code in this function runs in a blocking, synchronous manner.
|
58
|
+
"""
|
59
|
+
|
60
|
+
print(
|
61
|
+
f"Format set: {report}\nparams: {json.dumps(params)}\nview_server: {view_server}\nview_url: {view_url}\nuser: {user}\nuser_pass: {user_pass}",
|
62
|
+
file=sys.stderr)
|
63
|
+
# Lazy import of settings to avoid circulars when optional args are None
|
64
|
+
# from pyegeria.config import settings as _settings
|
65
|
+
from pyegeria.config import settings as _settings
|
66
|
+
|
67
|
+
|
68
|
+
return run_format_set_action_return(
|
69
|
+
format_set_name=report,
|
70
|
+
output_format="DICT",
|
71
|
+
params=params or {},
|
72
|
+
view_server=view_server if view_server is not None else _settings.Environment.egeria_view_server,
|
73
|
+
view_url=view_url if view_url is not None else _settings.Environment.egeria_view_server_url,
|
74
|
+
user=user if user is not None else _settings.User_Profile.user_name,
|
75
|
+
user_pass=user_pass if user_pass is not None else _settings.User_Profile.user_pwd,
|
76
|
+
)
|
77
|
+
# # Returning the hardcoded success for now to prove the async structure works.
|
78
|
+
# return {
|
79
|
+
# "status": "SUCCESS (Thread Test)",
|
80
|
+
# "report_name": report_name,
|
81
|
+
# "message": "The blocking call was successfully run on a separate thread, preventing timeout."
|
82
|
+
# }
|
83
|
+
|
84
|
+
|
85
|
+
def run_report(
|
86
|
+
*,
|
87
|
+
report: str,
|
88
|
+
params: Optional[Dict[str, Any]] = None,
|
89
|
+
view_server: Optional[str] = None,
|
90
|
+
view_url: Optional[str] = None,
|
91
|
+
user: Optional[str] = None,
|
92
|
+
user_pass: Optional[str] = None,
|
93
|
+
) -> Dict[str, Any]:
|
94
|
+
"""
|
95
|
+
Execute a format set action as an MCP-style tool. Enforces DICT/ALL by default.
|
96
|
+
Caller may pass credentials explicitly; otherwise defaults are used from config.
|
97
|
+
"""
|
98
|
+
print(f"Format set: {report}\nparams: {json.dumps(params)}\nview_server: {view_server}\nview_url: {view_url}\nuser: {user}\nuser_pass: {user_pass}", file=sys.stderr)
|
99
|
+
# Lazy import of settings to avoid circulars when optional args are None
|
100
|
+
from pyegeria.config import settings as _settings
|
101
|
+
logger.info(f"Format set: {formatSet}\nparams: {json.dumps(params)}\nview_server: {view_server}\nview_url: {view_url}\nuser: {user}\nuser_pass: {user_pass}")
|
102
|
+
return run_format_set_action_return(
|
103
|
+
format_set_name=report,
|
104
|
+
output_format="DICT",
|
105
|
+
params=params or {},
|
106
|
+
view_server=view_server if view_server is not None else _settings.Environment.egeria_view_server,
|
107
|
+
view_url=view_url if view_url is not None else _settings.Environment.egeria_view_server_url,
|
108
|
+
user=user if user is not None else _settings.User_Profile.user_name,
|
109
|
+
user_pass=user_pass if user_pass is not None else _settings.User_Profile.user_pwd,
|
110
|
+
)
|
pyegeria/mcp_server.py
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
"""PDX-License-Identifier: Apache-2.0
|
2
|
+
Copyright Contributors to the ODPi Egeria project.
|
3
|
+
|
4
|
+
This module provides a basic MCP server for Egeria.
|
5
|
+
"""
|
6
|
+
import asyncio
|
7
|
+
import re
|
8
|
+
import sys
|
9
|
+
from typing import Any, Dict, Optional, List, Coroutine
|
10
|
+
|
11
|
+
try:
|
12
|
+
# We use Optional[] and List[] types, so we import them.
|
13
|
+
from mcp.server.fastmcp import FastMCP
|
14
|
+
print("MCP import successful...", file=sys.stderr)
|
15
|
+
except ImportError:
|
16
|
+
print("MCP import failed.", file=sys.stderr)
|
17
|
+
raise
|
18
|
+
|
19
|
+
from pyegeria.mcp_adapter import (
|
20
|
+
list_reports,
|
21
|
+
describe_report,
|
22
|
+
run_report, _execute_egeria_call_blocking,
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
def _ok(result: Dict[str, Any] ) -> Dict[str, Any]:
|
27
|
+
# Pass-through helper in case you want to normalize or add metadata
|
28
|
+
print("OK: Operation completed successfully.", file=sys.stderr)
|
29
|
+
return result
|
30
|
+
|
31
|
+
|
32
|
+
def main() -> None:
|
33
|
+
# Initialize the server
|
34
|
+
srv = FastMCP(name="pyegeria-mcp")
|
35
|
+
print("Starting MCP server...", file=sys.stderr)
|
36
|
+
|
37
|
+
# list_reports tool (formerly list_format_sets)
|
38
|
+
@srv.tool(name="list_reports")
|
39
|
+
def list_reports_tool() -> Dict[str, Any]:
|
40
|
+
"""Lists all available reports (FormatSets)."""
|
41
|
+
print("DEBUG: Listing reports...", file=sys.stderr)
|
42
|
+
return _ok(list_reports())
|
43
|
+
|
44
|
+
# describe_report tool (formerly describe_format_set)
|
45
|
+
@srv.tool(name="describe_report")
|
46
|
+
def describe_report_tool(name: str, output_type: str = "DICT") -> Dict[str, Any]:
|
47
|
+
"""Returns the schema and details for a specified report."""
|
48
|
+
# FastMCP handles validation of 'name' and 'output_type' types automatically.
|
49
|
+
print(f"DEBUG: Describing report: {name} with output type: {output_type}", file=sys.stderr)
|
50
|
+
try:
|
51
|
+
return _ok(describe_report(name, output_type))
|
52
|
+
except Exception as e:
|
53
|
+
print(f"DEBUG: Exception during describe_report: {str(e)}", file=sys.stderr)
|
54
|
+
raise
|
55
|
+
|
56
|
+
# run_report tool (formerly run_format_set_action)
|
57
|
+
@srv.tool(name="run_report")
|
58
|
+
async def run_report_tool(
|
59
|
+
report_name: str,
|
60
|
+
search_string: str = "*",
|
61
|
+
page_size: Optional[int] = None,
|
62
|
+
start_from: Optional[int] = None,
|
63
|
+
starts_with: Optional[bool] = None,
|
64
|
+
ends_with: Optional[bool] = None,
|
65
|
+
ignore_case: Optional[bool] = None,
|
66
|
+
output_format: str = "DICT"
|
67
|
+
) -> Dict[str, Any]:
|
68
|
+
|
69
|
+
"""Run a report with the specified parameters."""
|
70
|
+
print("DEBUG: Running report...", file=sys.stderr)
|
71
|
+
# 1. Automatic Validation: FastMCP/Pydantic ensures types are correct.
|
72
|
+
|
73
|
+
# 2. Manual Validation (for specific values like output_format)
|
74
|
+
if output_format not in ["DICT", "JSON", "REPORT", "MERMAID", "HTML"]:
|
75
|
+
print(f"DEBUG: Invalid output_format: {output_format}", file=sys.stderr)
|
76
|
+
raise ValueError(
|
77
|
+
f"Invalid output_format: {output_format}. Must be one of ['DICT', 'JSON', 'REPORT', 'MERMAID', 'HTML'].")
|
78
|
+
|
79
|
+
# 3. Build params dictionary with only non-None values for clean passing
|
80
|
+
params = {
|
81
|
+
"search_string": search_string,
|
82
|
+
"page_size": page_size,
|
83
|
+
"start_from": start_from,
|
84
|
+
"starts_with": starts_with,
|
85
|
+
"ends_with": ends_with,
|
86
|
+
"ignore_case": ignore_case,
|
87
|
+
}
|
88
|
+
# Filter out None values before passing to run_report
|
89
|
+
params = {k: v for k, v in params.items() if v is not None}
|
90
|
+
|
91
|
+
print(f"DEBUG: Running report={report_name} with params={params}", file=sys.stderr)
|
92
|
+
|
93
|
+
try:
|
94
|
+
|
95
|
+
result = await asyncio.to_thread(
|
96
|
+
_execute_egeria_call_blocking,
|
97
|
+
report = report_name,
|
98
|
+
params = params
|
99
|
+
)
|
100
|
+
print("DEBUG: run_report completed successfully", file=sys.stderr)
|
101
|
+
return _ok(result)
|
102
|
+
except Exception as e:
|
103
|
+
# Re-raise the exception to be sent back as a JSON-RPC error
|
104
|
+
print(f"DEBUG: Exception occurred: {str(e)}", file=sys.stderr)
|
105
|
+
raise
|
106
|
+
|
107
|
+
@srv.tool(name="prompt")
|
108
|
+
def natural_language_prompt(prompt: str) -> Dict[str, Any]:
|
109
|
+
"""
|
110
|
+
Handles natural language queries from the user.
|
111
|
+
In a production environment, this would call an LLM API.
|
112
|
+
"""
|
113
|
+
print(f"DEBUG: Received natural language prompt: {prompt}", file=sys.stderr)
|
114
|
+
|
115
|
+
# Example of simple logic: If the user asks to list reports, delegate to the tool.
|
116
|
+
if "list" in prompt.lower() and "reports" in prompt.lower():
|
117
|
+
print("DEBUG: Delegating prompt to list_reports tool.", file=sys.stderr)
|
118
|
+
return list_reports() # Call the standard tool function directly
|
119
|
+
elif "run" in prompt.lower() and "report" in prompt.lower():
|
120
|
+
print("DEBUG: Delegating prompt to run_report tool.", file=sys.stderr)
|
121
|
+
# Simple entity extraction for report name (Requires more robust logic in reality!)
|
122
|
+
# Let's assume the report name is the word immediately following "report"
|
123
|
+
|
124
|
+
match = re.search(r'report\s+([a-zA-Z0-9]+)', prompt, re.IGNORECASE)
|
125
|
+
report_name = match.group(1) if match else None
|
126
|
+
|
127
|
+
if report_name:
|
128
|
+
print(f"DEBUG: Extracted report name: {report_name}", file=sys.stderr)
|
129
|
+
|
130
|
+
# Use another simple regex to look for page size
|
131
|
+
page_size_match = re.search(r'page size of\s+(\d+)', prompt, re.IGNORECASE)
|
132
|
+
page_size = int(page_size_match.group(1)) if page_size_match else None
|
133
|
+
|
134
|
+
search_match = re.search(r'search for\s+(.*?)(?:\s+in\s+report|\.|$)', prompt, re.IGNORECASE)
|
135
|
+
|
136
|
+
if search_match:
|
137
|
+
# Extract the content captured by the group (.*?)
|
138
|
+
search_string = search_match.group(1).strip()
|
139
|
+
|
140
|
+
# Check if the search string is meaningful
|
141
|
+
if search_string:
|
142
|
+
# Use a default report for demonstration purposes
|
143
|
+
|
144
|
+
print(
|
145
|
+
f"DEBUG: Delegating prompt to run_report tool. Report: {report_name}, Search: '{search_string}'",
|
146
|
+
file=sys.stderr)
|
147
|
+
|
148
|
+
# Call the standard tool function with extracted parameters
|
149
|
+
return run_report_tool(
|
150
|
+
report_name=report_name,
|
151
|
+
page_size=page_size,
|
152
|
+
search_string=search_string
|
153
|
+
)
|
154
|
+
|
155
|
+
# Delegate to the run_report_tool with the extracted parameters
|
156
|
+
return run_report_tool(
|
157
|
+
report_name=report_name,
|
158
|
+
page_size=page_size
|
159
|
+
)
|
160
|
+
# Fallback: Just confirm the prompt was received.
|
161
|
+
return {
|
162
|
+
"response": f"Acknowledged natural language query: '{prompt}'. This would be sent to an LLM."
|
163
|
+
}
|
164
|
+
|
165
|
+
# CRITICAL: This is the missing step. It tells the server to read and process
|
166
|
+
# JSON-RPC messages from standard input (stdin).
|
167
|
+
srv.run()
|
168
|
+
print("MCP server finished running.", file=sys.stderr)
|
169
|
+
|
170
|
+
|
171
|
+
if __name__ == "__main__":
|
172
|
+
main()
|
pyegeria/project_manager.py
CHANGED
@@ -915,7 +915,7 @@ class ProjectManager(Client2):
|
|
915
915
|
"""
|
916
916
|
|
917
917
|
url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/project-manager/projects/from-template"
|
918
|
-
return await self.
|
918
|
+
return await self._async_create_element_from_template(url, body)
|
919
919
|
|
920
920
|
@dynamic_catch
|
921
921
|
def create_project_from_template(
|
pyegeria/reference_data.py
CHANGED
@@ -652,7 +652,7 @@ class ReferenceDataManager(Client2):
|
|
652
652
|
"""
|
653
653
|
|
654
654
|
url = f"{self.ref_data_command_base}/valid-value-definitions/from-template"
|
655
|
-
return await self.
|
655
|
+
return await self._async_create_element_from_template(url, body)
|
656
656
|
|
657
657
|
@dynamic_catch
|
658
658
|
def create_valid_value_definition_from_template(
|
pyegeria/x_action_author_omvs.py
CHANGED
@@ -49,7 +49,7 @@ class ActionAuthor(AutomatedCuration):
|
|
49
49
|
)
|
50
50
|
self.action_command_root = f"{platform_url}/servers/"
|
51
51
|
|
52
|
-
async def
|
52
|
+
async def _async_x_create_element_from_template(
|
53
53
|
self, body: str, server: str = None
|
54
54
|
) -> str:
|
55
55
|
"""Create a metadata element from a template. Async version.
|
@@ -1,40 +1,37 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: pyegeria
|
3
|
-
Version: 5.4.
|
3
|
+
Version: 5.4.7
|
4
4
|
Summary: A python client for Egeria
|
5
|
-
|
5
|
+
Author-email: Dan Wolfson <dan.wolfson@pdr-associates.com>
|
6
|
+
License-Expression: Apache-2.0
|
6
7
|
Keywords: egeria,metadata,governance
|
7
|
-
Author: Dan Wolfson
|
8
|
-
Author-email: dan.wolfson@pdr-associates.com
|
9
|
-
Requires-Python: >3.12,<4.0.0
|
10
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
11
|
-
Classifier: License :: Other/Proprietary License
|
12
8
|
Classifier: Programming Language :: Python
|
13
9
|
Classifier: Programming Language :: Python :: 3
|
14
|
-
|
15
|
-
|
10
|
+
Requires-Python: >3.12
|
11
|
+
Description-Content-Type: text/markdown
|
12
|
+
License-File: LICENSE
|
16
13
|
Requires-Dist: httpx
|
17
|
-
Requires-Dist: inflect (>=7.5.0,<8.0.0)
|
18
|
-
Requires-Dist: jupyter
|
19
|
-
Requires-Dist: jupyter-notebook-parser (>=0.1.4,<0.2.0)
|
20
|
-
Requires-Dist: loguru (>=0.7.3,<0.8.0)
|
21
|
-
Requires-Dist: mermaid-py
|
22
|
-
Requires-Dist: poetry-core (>=2.1.3,<3.0.0)
|
23
|
-
Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0)
|
24
|
-
Requires-Dist: pydantic (>=2.11.7,<3.0.0)
|
25
|
-
Requires-Dist: pydantic-settings (>=2.10.1,<3.0.0)
|
26
|
-
Requires-Dist: pydevd-pycharm (>=252.23892.364,<253.0.0)
|
27
|
-
Requires-Dist: pytest (>=8.3.5,<9.0.0)
|
28
|
-
Requires-Dist: requests
|
29
14
|
Requires-Dist: rich
|
30
|
-
Requires-Dist: textual
|
31
|
-
Requires-Dist: trogon (>=0.6.0,<0.7.0)
|
32
|
-
Requires-Dist: urllib3
|
33
15
|
Requires-Dist: validators
|
34
|
-
Requires-Dist:
|
35
|
-
|
36
|
-
|
37
|
-
|
16
|
+
Requires-Dist: urllib3
|
17
|
+
Requires-Dist: requests
|
18
|
+
Requires-Dist: jupyter
|
19
|
+
Requires-Dist: click
|
20
|
+
Requires-Dist: trogon
|
21
|
+
Requires-Dist: textual
|
22
|
+
Requires-Dist: mermaid-py
|
23
|
+
Requires-Dist: psycopg2-binary
|
24
|
+
Requires-Dist: jupyter-notebook-parser
|
25
|
+
Requires-Dist: loguru
|
26
|
+
Requires-Dist: inflect
|
27
|
+
Requires-Dist: pydantic>=2.11.7
|
28
|
+
Requires-Dist: pydantic-settings>=2.10.1
|
29
|
+
Requires-Dist: pydevd-pycharm>=252.23892.364
|
30
|
+
Requires-Dist: wcwidth
|
31
|
+
Requires-Dist: altair
|
32
|
+
Requires-Dist: modelcontextprotocol
|
33
|
+
Requires-Dist: mcp>=1.15.0
|
34
|
+
Dynamic: license-file
|
38
35
|
|
39
36
|
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
40
37
|
<!-- Copyright Contributors to the ODPi Egeria project. -->
|