awslabs.healthlake-mcp-server 0.0.1__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.
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """Main entry point for the AWS HealthLake MCP server."""
17
+
18
+ # Standard library imports
19
+ import argparse
20
+ import asyncio
21
+ import os
22
+ import sys
23
+
24
+ # Local imports
25
+ from .server import create_healthlake_server
26
+
27
+ # Third-party imports
28
+ from loguru import logger
29
+ from mcp.server.stdio import stdio_server
30
+
31
+
32
+ # Configure logging
33
+ logger.remove()
34
+ logger.add(sys.stderr, level=os.getenv('MCP_LOG_LEVEL', 'WARNING'))
35
+
36
+
37
+ def parse_args():
38
+ """Parse command line arguments."""
39
+ parser = argparse.ArgumentParser(description='AWS HealthLake MCP Server')
40
+ parser.add_argument(
41
+ '--readonly',
42
+ action='store_true',
43
+ help='Run server in read-only mode (prevents all mutating operations)',
44
+ )
45
+ return parser.parse_args()
46
+
47
+
48
+ async def main() -> None:
49
+ """Main entry point for the server."""
50
+ try:
51
+ # Parse command line arguments
52
+ args = parse_args()
53
+
54
+ # Create the HealthLake MCP server with read-only mode
55
+ server = create_healthlake_server(read_only=args.readonly)
56
+
57
+ # Log server mode
58
+ if args.readonly:
59
+ logger.info('Server started in READ-ONLY mode - mutating operations disabled')
60
+ else:
61
+ logger.info('Server started in FULL ACCESS mode')
62
+
63
+ # Run the server using stdio transport
64
+ async with stdio_server() as (read_stream, write_stream):
65
+ await server.run(read_stream, write_stream, server.create_initialization_options())
66
+ except Exception as e:
67
+ logger.error(f'Server error: {e}')
68
+ raise
69
+
70
+
71
+ def sync_main() -> None:
72
+ """Synchronous wrapper for the main function."""
73
+ asyncio.run(main())
74
+
75
+
76
+ if __name__ == '__main__':
77
+ sync_main()
@@ -0,0 +1,120 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Pydantic models for HealthLake MCP server."""
16
+
17
+ # Standard library imports
18
+ # Local imports
19
+ from .fhir_operations import DATASTORE_ID_LENGTH
20
+
21
+ # Third-party imports
22
+ from pydantic import BaseModel, Field, field_validator
23
+ from typing import Any, Dict, Optional
24
+
25
+
26
+ class FHIRResource(BaseModel):
27
+ """Base FHIR resource model."""
28
+
29
+ resourceType: str
30
+ id: Optional[str] = None
31
+ meta: Optional[Dict[str, Any]] = None
32
+
33
+
34
+ class SearchParameters(BaseModel):
35
+ """FHIR search parameters."""
36
+
37
+ parameters: Dict[str, str] = Field(default_factory=dict)
38
+ count: int = Field(default=100, ge=1, le=100)
39
+
40
+
41
+ class CreateResourceRequest(BaseModel):
42
+ """Request to create a FHIR resource."""
43
+
44
+ datastore_id: str = Field(..., min_length=DATASTORE_ID_LENGTH, max_length=DATASTORE_ID_LENGTH)
45
+ resource_type: str
46
+ resource_data: Dict[str, Any]
47
+
48
+ @field_validator('datastore_id')
49
+ @classmethod
50
+ def validate_datastore_id(cls, v):
51
+ """Validate datastore ID is alphanumeric."""
52
+ if not v.isalnum():
53
+ raise ValueError('Datastore ID must be alphanumeric')
54
+ return v
55
+
56
+
57
+ class UpdateResourceRequest(BaseModel):
58
+ """Request to update a FHIR resource."""
59
+
60
+ datastore_id: str = Field(..., min_length=DATASTORE_ID_LENGTH, max_length=DATASTORE_ID_LENGTH)
61
+ resource_type: str
62
+ resource_id: str
63
+ resource_data: Dict[str, Any]
64
+
65
+ @field_validator('datastore_id')
66
+ @classmethod
67
+ def validate_datastore_id(cls, v):
68
+ """Validate datastore ID is alphanumeric."""
69
+ if not v.isalnum():
70
+ raise ValueError('Datastore ID must be alphanumeric')
71
+ return v
72
+
73
+
74
+ class DatastoreFilter(BaseModel):
75
+ """Filter for listing datastores."""
76
+
77
+ status: Optional[str] = Field(None, pattern='^(CREATING|ACTIVE|DELETING|DELETED)$')
78
+
79
+
80
+ class ImportJobConfig(BaseModel):
81
+ """Configuration for FHIR import job."""
82
+
83
+ datastore_id: str = Field(..., min_length=DATASTORE_ID_LENGTH, max_length=DATASTORE_ID_LENGTH)
84
+ input_data_config: Dict[str, Any]
85
+ data_access_role_arn: str
86
+ job_name: Optional[str] = None
87
+
88
+ @field_validator('datastore_id')
89
+ @classmethod
90
+ def validate_datastore_id(cls, v):
91
+ """Validate datastore ID is alphanumeric."""
92
+ if not v.isalnum():
93
+ raise ValueError('Datastore ID must be alphanumeric')
94
+ return v
95
+
96
+
97
+ class ExportJobConfig(BaseModel):
98
+ """Configuration for FHIR export job."""
99
+
100
+ datastore_id: str = Field(..., min_length=DATASTORE_ID_LENGTH, max_length=DATASTORE_ID_LENGTH)
101
+ output_data_config: Dict[str, Any]
102
+ data_access_role_arn: str
103
+ job_name: Optional[str] = None
104
+
105
+ @field_validator('datastore_id')
106
+ @classmethod
107
+ def validate_datastore_id(cls, v):
108
+ """Validate datastore ID is alphanumeric."""
109
+ if not v.isalnum():
110
+ raise ValueError('Datastore ID must be alphanumeric')
111
+ return v
112
+
113
+
114
+ class JobFilter(BaseModel):
115
+ """Filter for listing jobs."""
116
+
117
+ job_status: Optional[str] = Field(
118
+ None, pattern='^(SUBMITTED|IN_PROGRESS|COMPLETED|FAILED|STOP_REQUESTED|STOPPED)$'
119
+ )
120
+ job_type: Optional[str] = Field(None, pattern='^(IMPORT|EXPORT)$')