konokenj.cdk-api-mcp-server 0.0.1__py3-none-any.whl → 0.2.0__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.
Potentially problematic release.
This version of konokenj.cdk-api-mcp-server might be problematic. Click here for more details.
- cdk_api_mcp_server/__about__.py +1 -1
- cdk_api_mcp_server/__init__.py +1 -1
- cdk_api_mcp_server/models.py +24 -0
- cdk_api_mcp_server/resources.py +161 -0
- cdk_api_mcp_server/server.py +212 -3
- konokenj_cdk_api_mcp_server-0.2.0.dist-info/METADATA +79 -0
- konokenj_cdk_api_mcp_server-0.2.0.dist-info/RECORD +11 -0
- cdk_api_mcp_server/core/__init__.py +0 -1
- cdk_api_mcp_server/core/resources.py +0 -121
- cdk_api_mcp_server/core/server.py +0 -255
- konokenj_cdk_api_mcp_server-0.0.1.dist-info/METADATA +0 -45
- konokenj_cdk_api_mcp_server-0.0.1.dist-info/RECORD +0 -12
- {konokenj_cdk_api_mcp_server-0.0.1.dist-info → konokenj_cdk_api_mcp_server-0.2.0.dist-info}/WHEEL +0 -0
- {konokenj_cdk_api_mcp_server-0.0.1.dist-info → konokenj_cdk_api_mcp_server-0.2.0.dist-info}/entry_points.txt +0 -0
- {konokenj_cdk_api_mcp_server-0.0.1.dist-info → konokenj_cdk_api_mcp_server-0.2.0.dist-info}/licenses/LICENSE.txt +0 -0
cdk_api_mcp_server/__about__.py
CHANGED
cdk_api_mcp_server/__init__.py
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""AWS CDK API MCP model definitions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FileItem(BaseModel):
|
|
11
|
+
"""File item model for CDK API documentation."""
|
|
12
|
+
|
|
13
|
+
name: str = Field(description="Name of the file")
|
|
14
|
+
uri: str = Field(description="URI of the file")
|
|
15
|
+
is_directory: bool = Field(description="Whether the item is a directory")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FileList(BaseModel):
|
|
19
|
+
"""List of files in CDK API documentation."""
|
|
20
|
+
|
|
21
|
+
files: List[FileItem] = Field(default_factory=list, description="List of files")
|
|
22
|
+
error: Optional[str] = Field(
|
|
23
|
+
default=None, description="Error message if files not found"
|
|
24
|
+
)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""AWS CDK API MCP resource handlers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from importlib.resources import files
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import List
|
|
11
|
+
|
|
12
|
+
# Set up logging
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ResourceProvider(ABC):
|
|
17
|
+
"""リソースプロバイダーのインターフェース"""
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def get_resource_content(self, path: str) -> str:
|
|
21
|
+
"""リソースの内容を取得する"""
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def list_resources(self, path: str) -> List[str]:
|
|
25
|
+
"""指定パスのリソース一覧を取得する"""
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def resource_exists(self, path: str) -> bool:
|
|
29
|
+
"""リソースが存在するかチェックする"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class PackageResourceProvider(ResourceProvider):
|
|
33
|
+
"""Pythonパッケージからリソースを提供するプロバイダー"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, package_name: str = "cdk_api_mcp_server"):
|
|
36
|
+
self.package_name = package_name
|
|
37
|
+
|
|
38
|
+
def get_resource_content(self, path: str) -> str:
|
|
39
|
+
"""新しいimportlib.resourcesのAPIを使用してパッケージからリソースを読み込む"""
|
|
40
|
+
try:
|
|
41
|
+
# 末尾のパス部分を分離(ディレクトリとファイル名)
|
|
42
|
+
parts = path.strip("/").split("/")
|
|
43
|
+
|
|
44
|
+
if len(parts) < 1:
|
|
45
|
+
return "Error: Invalid resource path"
|
|
46
|
+
|
|
47
|
+
# パスが"constructs"で始まる場合は"aws-cdk/constructs"に変換
|
|
48
|
+
if parts[0] == "constructs":
|
|
49
|
+
parts[0] = "aws-cdk/constructs"
|
|
50
|
+
|
|
51
|
+
# resources配下の実際のファイルへのパスを構築
|
|
52
|
+
base_path = files(self.package_name).joinpath("resources")
|
|
53
|
+
|
|
54
|
+
# パス要素を結合
|
|
55
|
+
resource_path = base_path
|
|
56
|
+
for part in parts[0].split("/"):
|
|
57
|
+
resource_path = resource_path.joinpath(part)
|
|
58
|
+
|
|
59
|
+
for part in parts[1:]:
|
|
60
|
+
resource_path = resource_path.joinpath(part)
|
|
61
|
+
|
|
62
|
+
# ファイルとして存在するかチェック
|
|
63
|
+
if resource_path.is_file():
|
|
64
|
+
return resource_path.read_text(encoding="utf-8")
|
|
65
|
+
elif resource_path.is_dir():
|
|
66
|
+
# ディレクトリの場合は内容一覧を返す
|
|
67
|
+
dir_contents = [entry.name for entry in resource_path.iterdir()]
|
|
68
|
+
return f"Directory: {path}\nContents: {', '.join(sorted(dir_contents))}"
|
|
69
|
+
else:
|
|
70
|
+
return f"Error: Resource '{path}' not found"
|
|
71
|
+
except (FileNotFoundError, IsADirectoryError, PermissionError) as e:
|
|
72
|
+
logger.debug(f"リソースの取得に失敗: {path} - {e}")
|
|
73
|
+
return f"Error: Resource '{path}' not found - {e!s}"
|
|
74
|
+
|
|
75
|
+
def list_resources(self, path: str) -> List[str]:
|
|
76
|
+
"""新しいimportlib.resourcesのAPIを使用してパッケージ内のリソース一覧を取得する"""
|
|
77
|
+
try:
|
|
78
|
+
# resources配下の実際のディレクトリへのパスを構築
|
|
79
|
+
base_path = files(self.package_name).joinpath("resources")
|
|
80
|
+
|
|
81
|
+
# パス要素を結合
|
|
82
|
+
resource_path = base_path
|
|
83
|
+
if path:
|
|
84
|
+
parts = path.strip("/").split("/")
|
|
85
|
+
# パスが"constructs"で始まる場合は"aws-cdk/constructs"に変換
|
|
86
|
+
if parts[0] == "constructs":
|
|
87
|
+
parts[0] = "aws-cdk/constructs"
|
|
88
|
+
|
|
89
|
+
# パスの最初の部分("aws-cdk/constructs"を含む)を分割して追加
|
|
90
|
+
for part in parts[0].split("/"):
|
|
91
|
+
resource_path = resource_path.joinpath(part)
|
|
92
|
+
|
|
93
|
+
# 残りのパス要素を追加
|
|
94
|
+
for part in parts[1:]:
|
|
95
|
+
resource_path = resource_path.joinpath(part)
|
|
96
|
+
|
|
97
|
+
# ディレクトリとして存在するかチェック
|
|
98
|
+
if resource_path.is_dir():
|
|
99
|
+
items = sorted([entry.name for entry in resource_path.iterdir()])
|
|
100
|
+
|
|
101
|
+
# クライアントに返すときはハイフン形式に変換
|
|
102
|
+
if path and path.startswith("constructs/") and not path.endswith("/"):
|
|
103
|
+
# ディレクトリでないパスの場合、モジュール名として扱いハイフン形式にする
|
|
104
|
+
return [item.replace("_", "-") for item in items]
|
|
105
|
+
return items
|
|
106
|
+
else:
|
|
107
|
+
return []
|
|
108
|
+
except (FileNotFoundError, NotADirectoryError, PermissionError) as e:
|
|
109
|
+
logger.debug(f"リソース一覧の取得に失敗: {path} - {e}")
|
|
110
|
+
return []
|
|
111
|
+
|
|
112
|
+
def resource_exists(self, path: str) -> bool:
|
|
113
|
+
"""新しいimportlib.resourcesのAPIを使用してリソースが存在するかチェックする"""
|
|
114
|
+
try:
|
|
115
|
+
# resources配下の実際のファイルへのパスを構築
|
|
116
|
+
base_path = files(self.package_name).joinpath("resources")
|
|
117
|
+
|
|
118
|
+
# パス要素を結合
|
|
119
|
+
resource_path = base_path
|
|
120
|
+
if path:
|
|
121
|
+
parts = path.strip("/").split("/")
|
|
122
|
+
# パスが"constructs"で始まる場合は"aws-cdk/constructs"に変換
|
|
123
|
+
if parts[0] == "constructs":
|
|
124
|
+
parts[0] = "aws-cdk/constructs"
|
|
125
|
+
|
|
126
|
+
# パスの最初の部分("aws-cdk/constructs"を含む)を分割して追加
|
|
127
|
+
for part in parts[0].split("/"):
|
|
128
|
+
resource_path = resource_path.joinpath(part)
|
|
129
|
+
|
|
130
|
+
# 残りのパス要素を追加
|
|
131
|
+
for part in parts[1:]:
|
|
132
|
+
resource_path = resource_path.joinpath(part)
|
|
133
|
+
|
|
134
|
+
# 存在チェック - Traversableには.exists()がないので、is_file()とis_dir()で確認
|
|
135
|
+
return resource_path.is_file() or resource_path.is_dir()
|
|
136
|
+
except (FileNotFoundError, PermissionError) as e:
|
|
137
|
+
logger.debug(f"リソースの存在チェックに失敗: {path} - {e}")
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# Define resource directories for backward compatibility with tests
|
|
142
|
+
CONSTRUCTS_DIR = Path(__file__).parent / "resources" / "aws-cdk" / "constructs"
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def get_package_content(provider: ResourceProvider, package_name: str) -> str:
|
|
146
|
+
"""Get content for a package resource as a simple JSON array.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
provider: Resource provider
|
|
150
|
+
package_name: Package name
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
JSON array of module names as a string
|
|
154
|
+
"""
|
|
155
|
+
resource_path = f"constructs/{package_name}"
|
|
156
|
+
|
|
157
|
+
if not provider.resource_exists(resource_path):
|
|
158
|
+
return "[]" # 空の配列を返す
|
|
159
|
+
else:
|
|
160
|
+
modules = provider.list_resources(resource_path)
|
|
161
|
+
return json.dumps(modules)
|
cdk_api_mcp_server/server.py
CHANGED
|
@@ -1,8 +1,217 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
1
|
"""AWS CDK API MCP server implementation."""
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
import json
|
|
4
|
+
import mimetypes
|
|
5
|
+
import os
|
|
6
|
+
from typing import Optional
|
|
5
7
|
|
|
8
|
+
from fastmcp import FastMCP
|
|
9
|
+
from fastmcp.resources import TextResource
|
|
10
|
+
from pydantic import AnyUrl
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
from cdk_api_mcp_server.resources import (
|
|
13
|
+
PackageResourceProvider,
|
|
14
|
+
ResourceProvider,
|
|
15
|
+
get_package_content,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# MIMEタイプの初期化と追加
|
|
19
|
+
mimetypes.init()
|
|
20
|
+
mimetypes.add_type("text/markdown", ".md")
|
|
21
|
+
mimetypes.add_type("text/typescript", ".ts")
|
|
22
|
+
mimetypes.add_type("application/json", ".json")
|
|
23
|
+
|
|
24
|
+
# デフォルトのMCPサーバーインスタンス
|
|
25
|
+
mcp: FastMCP = FastMCP()
|
|
26
|
+
# デフォルトのリソースプロバイダー
|
|
27
|
+
_default_provider = PackageResourceProvider()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def create_server(provider: Optional[ResourceProvider] = None) -> FastMCP:
|
|
31
|
+
"""Create an MCP server with the given resource provider.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
provider: ResourceProvider for CDK API resources. Defaults to PackageResourceProvider.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
FastMCP server instance with registered resources
|
|
38
|
+
"""
|
|
39
|
+
# 使用するリソースプロバイダー
|
|
40
|
+
resource_provider = provider or _default_provider
|
|
41
|
+
|
|
42
|
+
# 新しいサーバーインスタンスを作成
|
|
43
|
+
server: FastMCP = FastMCP()
|
|
44
|
+
|
|
45
|
+
# nameフィールドにアクセスする方法は提供されていないため、descriptionを使う
|
|
46
|
+
server.description = "AWS CDK API MCP Server"
|
|
47
|
+
|
|
48
|
+
# 定義済みのパッケージとして直接リソース登録
|
|
49
|
+
@server.resource("cdk-api-docs://constructs/@aws-cdk", mime_type="application/json")
|
|
50
|
+
def get_aws_cdk_alpha_packages():
|
|
51
|
+
"""Get AWS CDK Alpha modules published in @aws-cdk namespace."""
|
|
52
|
+
content = get_package_content(resource_provider, "@aws-cdk")
|
|
53
|
+
|
|
54
|
+
# JSONとしてレスポンスを返す
|
|
55
|
+
return TextResource(
|
|
56
|
+
uri=AnyUrl.build(
|
|
57
|
+
scheme="cdk-api-docs", host="constructs", path="/@aws-cdk"
|
|
58
|
+
),
|
|
59
|
+
name="@aws-cdk",
|
|
60
|
+
text=content,
|
|
61
|
+
description="AWS CDK Alpha modules",
|
|
62
|
+
mime_type="application/json", # JSONレスポンスのMIMEタイプを設定
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@server.resource(
|
|
66
|
+
"cdk-api-docs://constructs/aws-cdk-lib", mime_type="application/json"
|
|
67
|
+
)
|
|
68
|
+
def get_aws_cdk_lib_packages():
|
|
69
|
+
"""Get AWS CDK Stable modules in aws-cdk-lib package."""
|
|
70
|
+
content = get_package_content(resource_provider, "aws-cdk-lib")
|
|
71
|
+
|
|
72
|
+
# JSONとしてレスポンスを返す
|
|
73
|
+
return TextResource(
|
|
74
|
+
uri=AnyUrl.build(
|
|
75
|
+
scheme="cdk-api-docs", host="constructs", path="/aws-cdk-lib"
|
|
76
|
+
),
|
|
77
|
+
name="aws-cdk-lib",
|
|
78
|
+
text=content,
|
|
79
|
+
description="AWS CDK Stable modules",
|
|
80
|
+
mime_type="application/json", # JSONレスポンスのMIMEタイプを設定
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# リソーステンプレート:パッケージ内のモジュール一覧
|
|
84
|
+
@server.resource(
|
|
85
|
+
"cdk-api-docs://constructs/{package_name}/", mime_type="application/json"
|
|
86
|
+
)
|
|
87
|
+
def list_package_modules(package_name: str):
|
|
88
|
+
"""List all modules in a package."""
|
|
89
|
+
modules = [
|
|
90
|
+
item
|
|
91
|
+
for item in resource_provider.list_resources(f"constructs/{package_name}")
|
|
92
|
+
if resource_provider.resource_exists(f"constructs/{package_name}/{item}/")
|
|
93
|
+
]
|
|
94
|
+
content = json.dumps(modules)
|
|
95
|
+
|
|
96
|
+
# JSONとしてレスポンスを返す
|
|
97
|
+
return TextResource(
|
|
98
|
+
uri=AnyUrl.build(
|
|
99
|
+
scheme="cdk-api-docs", host="constructs", path=f"/{package_name}/"
|
|
100
|
+
),
|
|
101
|
+
name=f"{package_name}-modules",
|
|
102
|
+
text=content,
|
|
103
|
+
description=f"Modules in {package_name}",
|
|
104
|
+
mime_type="application/json", # JSONレスポンスのMIMEタイプを設定
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# リソーステンプレート:モジュール内のファイル一覧
|
|
108
|
+
@server.resource(
|
|
109
|
+
"cdk-api-docs://constructs/{package_name}/{module_name}/",
|
|
110
|
+
mime_type="application/json",
|
|
111
|
+
)
|
|
112
|
+
def list_module_files(package_name: str, module_name: str):
|
|
113
|
+
"""List all files in a module."""
|
|
114
|
+
files = resource_provider.list_resources(
|
|
115
|
+
f"constructs/{package_name}/{module_name}"
|
|
116
|
+
)
|
|
117
|
+
content = json.dumps(files)
|
|
118
|
+
|
|
119
|
+
# JSONとしてレスポンスを返す
|
|
120
|
+
return TextResource(
|
|
121
|
+
uri=AnyUrl.build(
|
|
122
|
+
scheme="cdk-api-docs",
|
|
123
|
+
host="constructs",
|
|
124
|
+
path=f"/{package_name}/{module_name}/",
|
|
125
|
+
),
|
|
126
|
+
name=f"{module_name}-files",
|
|
127
|
+
text=content,
|
|
128
|
+
description=f"Files in {package_name}/{module_name}",
|
|
129
|
+
mime_type="application/json", # JSONレスポンスのMIMEタイプを設定
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# リソーステンプレート:すべてのファイルタイプ対応
|
|
133
|
+
@server.resource(
|
|
134
|
+
"cdk-api-docs://constructs/{package_name}/{module_name}/{file_name}"
|
|
135
|
+
)
|
|
136
|
+
def get_construct_file(package_name: str, module_name: str, file_name: str):
|
|
137
|
+
"""Get a file from the constructs directory."""
|
|
138
|
+
resource_path = f"constructs/{package_name}/{module_name}/{file_name}"
|
|
139
|
+
|
|
140
|
+
if not resource_provider.resource_exists(resource_path):
|
|
141
|
+
error_message = f"Error: File '{resource_path}' not found"
|
|
142
|
+
return TextResource(
|
|
143
|
+
uri=AnyUrl.build(
|
|
144
|
+
scheme="cdk-api-docs",
|
|
145
|
+
host="constructs",
|
|
146
|
+
path=f"/{package_name}/{module_name}/{file_name}",
|
|
147
|
+
),
|
|
148
|
+
name=file_name,
|
|
149
|
+
text=error_message,
|
|
150
|
+
description=f"Error: {resource_path}",
|
|
151
|
+
mime_type="text/plain",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# リソースプロバイダーからコンテンツを取得
|
|
155
|
+
content = resource_provider.get_resource_content(resource_path)
|
|
156
|
+
|
|
157
|
+
# 拡張子に基づいてMIMEタイプを決定
|
|
158
|
+
_, ext = os.path.splitext(file_name)
|
|
159
|
+
|
|
160
|
+
# 特定の拡張子に対して明示的にMIMEタイプを設定
|
|
161
|
+
if ext == ".md":
|
|
162
|
+
mime_type = "text/markdown"
|
|
163
|
+
description = f"Markdown file: {package_name}/{module_name}/{file_name}"
|
|
164
|
+
elif ext == ".ts":
|
|
165
|
+
mime_type = "text/typescript"
|
|
166
|
+
description = f"TypeScript file: {package_name}/{module_name}/{file_name}"
|
|
167
|
+
elif ext == ".json":
|
|
168
|
+
mime_type = "application/json"
|
|
169
|
+
description = f"JSON file: {package_name}/{module_name}/{file_name}"
|
|
170
|
+
else:
|
|
171
|
+
# その他の場合はmimetypesモジュールで判定
|
|
172
|
+
mime_type, _ = mimetypes.guess_type(file_name)
|
|
173
|
+
if mime_type is None:
|
|
174
|
+
# デフォルトはプレーンテキスト
|
|
175
|
+
mime_type = "text/plain"
|
|
176
|
+
description = f"File: {package_name}/{module_name}/{file_name}"
|
|
177
|
+
|
|
178
|
+
# Create and return a TextResource
|
|
179
|
+
return TextResource(
|
|
180
|
+
uri=AnyUrl.build(
|
|
181
|
+
scheme="cdk-api-docs",
|
|
182
|
+
host="constructs",
|
|
183
|
+
path=f"/{package_name}/{module_name}/{file_name}",
|
|
184
|
+
),
|
|
185
|
+
name=file_name,
|
|
186
|
+
text=content,
|
|
187
|
+
description=description,
|
|
188
|
+
mime_type=mime_type,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
return server
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
# デフォルトのサーバーを初期化
|
|
195
|
+
def initialize_default_server() -> None:
|
|
196
|
+
"""Initialize the default MCP server with resources."""
|
|
197
|
+
global mcp
|
|
198
|
+
default_server = create_server(_default_provider)
|
|
199
|
+
# 以前のmcpの属性を新しいサーバーにコピー
|
|
200
|
+
mcp.__dict__.update(default_server.__dict__)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# デフォルトサーバーを初期化
|
|
204
|
+
initialize_default_server()
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def main():
|
|
208
|
+
"""Run the MCP server."""
|
|
209
|
+
import logging
|
|
210
|
+
|
|
211
|
+
logging.basicConfig(level=logging.INFO)
|
|
212
|
+
# サーバーを実行
|
|
213
|
+
mcp.run()
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
if __name__ == "__main__":
|
|
8
217
|
main()
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: konokenj.cdk-api-mcp-server
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: An MCP server provides AWS CDK API Reference
|
|
5
|
+
Project-URL: Documentation, https://github.com/konokenj/cdk-api-mcp-server#readme
|
|
6
|
+
Project-URL: Issues, https://github.com/konokenj/cdk-api-mcp-server/issues
|
|
7
|
+
Project-URL: Source, https://github.com/konokenj/cdk-api-mcp-server
|
|
8
|
+
Author-email: Kenji Kono <konoken@amazon.co.jp>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE.txt
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Requires-Dist: fastmcp>=2.0.0
|
|
22
|
+
Requires-Dist: pydantic>=2.10.6
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
25
|
+
Requires-Dist: pygithub; extra == 'dev'
|
|
26
|
+
Requires-Dist: semantic-version; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# CDK API MCP Server
|
|
30
|
+
|
|
31
|
+
[](https://pypi.org/project/konokenj.cdk-api-mcp-server)
|
|
32
|
+
[](https://pypi.org/project/konokenj.cdk-api-mcp-server)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
Add to your mcp.json:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"mcpServers": {
|
|
43
|
+
"konokenj.cdk-api-mcp-server": {
|
|
44
|
+
"command": "uvx",
|
|
45
|
+
"args": ["konokenj.cdk-api-mcp-server@latest"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## MCP Server Capabilities
|
|
52
|
+
|
|
53
|
+
### Resource: CDK API packages
|
|
54
|
+
|
|
55
|
+
Registered as static resources. To get available modules under the package, call `list_resources()` as MCP client.
|
|
56
|
+
|
|
57
|
+
- `cdk-api-docs://constructs/@aws-cdk` ... Alpha modules published in `@aws-cdk` namespace
|
|
58
|
+
- `cdk-api-docs://constructs/aws-cdk-lib` ... Stable modules in `aws-cdk-lib` package
|
|
59
|
+
|
|
60
|
+
### Resource Template: List modules in package
|
|
61
|
+
|
|
62
|
+
To get available documents under the module, call `read_resource(uri)` as MCP client.
|
|
63
|
+
|
|
64
|
+
> [!Note]
|
|
65
|
+
> Chagne first and second part of uri as you need.
|
|
66
|
+
|
|
67
|
+
- `cdk-api-docs://constructs/@aws-cdk/{module}/`
|
|
68
|
+
- `cdk-api-docs://constructs/aws-cdk-lib/{module}/`
|
|
69
|
+
|
|
70
|
+
### Resource Template: Read file contents
|
|
71
|
+
|
|
72
|
+
To read a document, call `read_resource(uri)` as MCP client.
|
|
73
|
+
|
|
74
|
+
- `cdk-api-docs://constructs/@aws-cdk/{module}/{file}`
|
|
75
|
+
- `cdk-api-docs://constructs/aws-cdk-lib/{module}/{file}`
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
Distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
cdk_api_mcp_server/__about__.py,sha256=tp7Scy_xXYQk3Bk2RAr7QoM8qhKmY61oQNQYmcMNQUk,128
|
|
2
|
+
cdk_api_mcp_server/__init__.py,sha256=yJA6yIEhJviC-qNlB-nC6UR1JblQci_d84i-viHZkc0,187
|
|
3
|
+
cdk_api_mcp_server/models.py,sha256=cMS1Hi29M41YjuBxqqrzNrNvyG3MgnUBb1SqYpMCJ30,692
|
|
4
|
+
cdk_api_mcp_server/resources.py,sha256=R7LVwn29I4BJzU5XAwKbX8j6uy-3ZxcB1b0HzZ_Z2PI,6689
|
|
5
|
+
cdk_api_mcp_server/server.py,sha256=QTJ_e1sDU4Z64hinJFgApCwA2tKt_ma21jgRFw7ZBdw,7836
|
|
6
|
+
cdk_api_mcp_server/resources/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
konokenj_cdk_api_mcp_server-0.2.0.dist-info/METADATA,sha256=floZlzg4_ivxSPAYYRIyeThv8AkCtZnOB1BIS1HKzPs,2678
|
|
8
|
+
konokenj_cdk_api_mcp_server-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
+
konokenj_cdk_api_mcp_server-0.2.0.dist-info/entry_points.txt,sha256=bVDhMdyCC1WNMPOMbmB82jvWII2CIrwTZDygdCf0cYQ,79
|
|
10
|
+
konokenj_cdk_api_mcp_server-0.2.0.dist-info/licenses/LICENSE.txt,sha256=5OIAASeg1HM22mVZ1enz9bgZ7TlsGfWXnj02P9OgFyk,1098
|
|
11
|
+
konokenj_cdk_api_mcp_server-0.2.0.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""Core module for CDK API MCP server."""
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""AWS CDK API MCP resource handlers."""
|
|
3
|
-
|
|
4
|
-
import logging
|
|
5
|
-
import os
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from typing import Optional
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# Set up logging
|
|
11
|
-
logger = logging.getLogger(__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# Define resource directories
|
|
15
|
-
DOCS_DIR = Path(__file__).parent.parent / "resources" / "aws-cdk" / "docs"
|
|
16
|
-
INTEG_TESTS_DIR = Path(__file__).parent.parent / "resources" / "aws-cdk" / "integ-tests"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
async def get_cdk_api_docs(category: str, package_name: str, module_name: str, file_path: str) -> str:
|
|
20
|
-
"""Get AWS CDK API documentation from the resources directory.
|
|
21
|
-
|
|
22
|
-
This resource handler serves documentation files from the resources/aws-cdk/docs directory.
|
|
23
|
-
The files are organized by category, package and module.
|
|
24
|
-
|
|
25
|
-
Example URIs:
|
|
26
|
-
- cdk-api-docs://packages/@aws-cdk/aws-s3/README.md
|
|
27
|
-
- cdk-api-docs://packages/aws-cdk-lib/aws-lambda/README.md
|
|
28
|
-
- cdk-api-docs://root/DEPRECATED_APIs.md
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
category: The category (e.g., 'packages', 'root')
|
|
32
|
-
package_name: The package name (e.g., '@aws-cdk', 'aws-cdk-lib')
|
|
33
|
-
module_name: The module name (e.g., 'aws-s3', 'aws-lambda')
|
|
34
|
-
file_path: The file path within the module (e.g., 'README.md')
|
|
35
|
-
|
|
36
|
-
Returns:
|
|
37
|
-
String containing the requested documentation
|
|
38
|
-
"""
|
|
39
|
-
# Handle special case for root files like DEPRECATED_APIs.md
|
|
40
|
-
if category == "root":
|
|
41
|
-
file_path = os.path.join(DOCS_DIR, package_name)
|
|
42
|
-
if os.path.exists(file_path):
|
|
43
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
|
44
|
-
return f.read()
|
|
45
|
-
else:
|
|
46
|
-
return f"Error: File '{package_name}' not found"
|
|
47
|
-
|
|
48
|
-
# For packages category, construct the file path
|
|
49
|
-
if category == "packages":
|
|
50
|
-
if file_path:
|
|
51
|
-
file_path = os.path.join(DOCS_DIR, category, package_name, module_name, file_path)
|
|
52
|
-
else:
|
|
53
|
-
file_path = os.path.join(DOCS_DIR, category, package_name, module_name)
|
|
54
|
-
else:
|
|
55
|
-
# For other categories, construct the path accordingly
|
|
56
|
-
if file_path:
|
|
57
|
-
file_path = os.path.join(DOCS_DIR, category, package_name, module_name, file_path)
|
|
58
|
-
else:
|
|
59
|
-
file_path = os.path.join(DOCS_DIR, category, package_name, module_name)
|
|
60
|
-
|
|
61
|
-
# Check if the file exists
|
|
62
|
-
if os.path.exists(file_path):
|
|
63
|
-
# If it's a directory, list the contents
|
|
64
|
-
if os.path.isdir(file_path):
|
|
65
|
-
files = os.listdir(file_path)
|
|
66
|
-
result = f"# Contents of {package_name}/{module_name}\n\n"
|
|
67
|
-
for f in sorted(files):
|
|
68
|
-
if os.path.isdir(os.path.join(file_path, f)):
|
|
69
|
-
result += f"- [{f}/](cdk-api-docs://{category}/{package_name}/{module_name}/{f})\n"
|
|
70
|
-
else:
|
|
71
|
-
result += f"- [{f}](cdk-api-docs://{category}/{package_name}/{module_name}/{f})\n"
|
|
72
|
-
return result
|
|
73
|
-
# If it's a file, return the contents
|
|
74
|
-
else:
|
|
75
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
|
76
|
-
return f.read()
|
|
77
|
-
else:
|
|
78
|
-
return f"Error: File '{file_path}' not found"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
async def get_cdk_api_integ_tests(module_name: str, file_path: Optional[str] = None) -> str:
|
|
82
|
-
"""Get AWS CDK integration test examples from the resources directory.
|
|
83
|
-
|
|
84
|
-
This resource handler serves integration test files from the resources/aws-cdk/integ-tests directory.
|
|
85
|
-
The files are organized by module.
|
|
86
|
-
|
|
87
|
-
Example URIs:
|
|
88
|
-
- cdk-api-integ-tests://aws-s3/aws-s3.test1.md
|
|
89
|
-
- cdk-api-integ-tests://aws-lambda/aws-lambda.handler.md
|
|
90
|
-
|
|
91
|
-
Args:
|
|
92
|
-
module_name: The module name (e.g., 'aws-s3', 'aws-lambda')
|
|
93
|
-
file_path: The file path within the module (e.g., 'aws-s3.test1.md')
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
String containing the requested integration test example
|
|
97
|
-
"""
|
|
98
|
-
# Construct the file path
|
|
99
|
-
if file_path:
|
|
100
|
-
file_path = os.path.join(INTEG_TESTS_DIR, module_name, file_path)
|
|
101
|
-
else:
|
|
102
|
-
file_path = os.path.join(INTEG_TESTS_DIR, module_name)
|
|
103
|
-
|
|
104
|
-
# Check if the file exists
|
|
105
|
-
if os.path.exists(file_path):
|
|
106
|
-
# If it's a directory, list the contents
|
|
107
|
-
if os.path.isdir(file_path):
|
|
108
|
-
files = os.listdir(file_path)
|
|
109
|
-
result = f"# Integration Tests for {module_name}\n\n"
|
|
110
|
-
for f in sorted(files):
|
|
111
|
-
if os.path.isdir(os.path.join(file_path, f)):
|
|
112
|
-
result += f"- [{f}/](cdk-api-integ-tests://{module_name}/{f})\n"
|
|
113
|
-
else:
|
|
114
|
-
result += f"- [{f}](cdk-api-integ-tests://{module_name}/{f})\n"
|
|
115
|
-
return result
|
|
116
|
-
# If it's a file, return the contents
|
|
117
|
-
else:
|
|
118
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
|
119
|
-
return f.read()
|
|
120
|
-
else:
|
|
121
|
-
return f"Error: File '{file_path}' not found"
|
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""AWS CDK API MCP server implementation."""
|
|
3
|
-
|
|
4
|
-
import logging
|
|
5
|
-
import os
|
|
6
|
-
import json
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from cdk_api_mcp_server.core import resources
|
|
9
|
-
from fastmcp import FastMCP
|
|
10
|
-
from fastmcp.resources import TextResource, DirectoryResource
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# Set up logging
|
|
14
|
-
logger = logging.getLogger(__name__)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# Define resource directories
|
|
18
|
-
DOCS_DIR = Path(__file__).parent.parent / "resources" / "aws-cdk" / "docs"
|
|
19
|
-
INTEG_TESTS_DIR = Path(__file__).parent.parent / "resources" / "aws-cdk" / "integ-tests"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# Create MCP server
|
|
23
|
-
mcp = FastMCP(
|
|
24
|
-
'AWS CDK API MCP Server',
|
|
25
|
-
dependencies=[],
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# Register resource templates for hierarchical navigation
|
|
30
|
-
@mcp.resource('cdk-api-docs://')
|
|
31
|
-
async def list_root_categories():
|
|
32
|
-
"""List all available categories in the CDK API documentation."""
|
|
33
|
-
if not DOCS_DIR.exists():
|
|
34
|
-
return {"error": "Documentation directory not found"}
|
|
35
|
-
|
|
36
|
-
categories = []
|
|
37
|
-
# Add root category
|
|
38
|
-
categories.append({
|
|
39
|
-
"name": "root",
|
|
40
|
-
"uri": "cdk-api-docs://root/",
|
|
41
|
-
"description": "Root level documentation files",
|
|
42
|
-
"is_directory": True
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
# Add packages category if it exists
|
|
46
|
-
packages_dir = DOCS_DIR / "packages"
|
|
47
|
-
if packages_dir.exists() and packages_dir.is_dir():
|
|
48
|
-
categories.append({
|
|
49
|
-
"name": "packages",
|
|
50
|
-
"uri": "cdk-api-docs://packages/",
|
|
51
|
-
"description": "AWS CDK packages documentation",
|
|
52
|
-
"is_directory": True
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
return json.dumps({"categories": categories})
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@mcp.resource('cdk-api-docs://root/')
|
|
59
|
-
def list_root_files():
|
|
60
|
-
"""List all files in the root directory of the CDK API documentation."""
|
|
61
|
-
if not DOCS_DIR.exists():
|
|
62
|
-
return {"error": "Documentation directory not found"}
|
|
63
|
-
|
|
64
|
-
files = []
|
|
65
|
-
for item in DOCS_DIR.iterdir():
|
|
66
|
-
if item.is_file():
|
|
67
|
-
files.append({
|
|
68
|
-
"name": item.name,
|
|
69
|
-
"uri": f"cdk-api-docs://root/{item.name}",
|
|
70
|
-
"is_directory": False
|
|
71
|
-
})
|
|
72
|
-
elif item.is_dir() and item.name != "packages": # Skip packages dir as it's handled separately
|
|
73
|
-
files.append({
|
|
74
|
-
"name": item.name,
|
|
75
|
-
"uri": f"cdk-api-docs://root/{item.name}/",
|
|
76
|
-
"is_directory": True
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
return json.dumps({"files": files})
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@mcp.resource('cdk-api-docs://root/{file_name}')
|
|
83
|
-
def get_root_file(file_name: str):
|
|
84
|
-
"""Get a file from the root directory of the CDK API documentation."""
|
|
85
|
-
file_path = DOCS_DIR / file_name
|
|
86
|
-
|
|
87
|
-
if not file_path.exists() or not file_path.is_file():
|
|
88
|
-
return f"Error: File '{file_name}' not found"
|
|
89
|
-
|
|
90
|
-
# Read the file content
|
|
91
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
|
92
|
-
content = f.read()
|
|
93
|
-
|
|
94
|
-
# Create and return a TextResource
|
|
95
|
-
return TextResource(
|
|
96
|
-
uri=f"cdk-api-docs://root/{file_name}",
|
|
97
|
-
name=file_name,
|
|
98
|
-
text=content,
|
|
99
|
-
description=f"Root documentation file: {file_name}",
|
|
100
|
-
mime_type="text/markdown" if file_name.endswith(".md") else "text/plain"
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@mcp.resource('cdk-api-docs://packages/')
|
|
105
|
-
def list_packages():
|
|
106
|
-
"""List all packages in the CDK API documentation."""
|
|
107
|
-
packages_dir = DOCS_DIR / "packages"
|
|
108
|
-
|
|
109
|
-
if not packages_dir.exists() or not packages_dir.is_dir():
|
|
110
|
-
return {"error": "Packages directory not found"}
|
|
111
|
-
|
|
112
|
-
packages = []
|
|
113
|
-
for item in packages_dir.iterdir():
|
|
114
|
-
if item.is_dir():
|
|
115
|
-
packages.append({
|
|
116
|
-
"name": item.name,
|
|
117
|
-
"uri": f"cdk-api-docs://packages/{item.name}/",
|
|
118
|
-
"is_directory": True
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
return json.dumps({"packages": packages})
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
@mcp.resource('cdk-api-docs://packages/{package_name}/')
|
|
125
|
-
def list_package_modules(package_name: str):
|
|
126
|
-
"""List all modules in a specific package."""
|
|
127
|
-
package_dir = DOCS_DIR / "packages" / package_name
|
|
128
|
-
|
|
129
|
-
if not package_dir.exists() or not package_dir.is_dir():
|
|
130
|
-
return {"error": f"Package '{package_name}' not found"}
|
|
131
|
-
|
|
132
|
-
modules = []
|
|
133
|
-
for item in package_dir.iterdir():
|
|
134
|
-
if item.is_dir():
|
|
135
|
-
modules.append({
|
|
136
|
-
"name": item.name,
|
|
137
|
-
"uri": f"cdk-api-docs://packages/{package_name}/{item.name}/",
|
|
138
|
-
"is_directory": True
|
|
139
|
-
})
|
|
140
|
-
elif item.is_file():
|
|
141
|
-
modules.append({
|
|
142
|
-
"name": item.name,
|
|
143
|
-
"uri": f"cdk-api-docs://packages/{package_name}/{item.name}",
|
|
144
|
-
"is_directory": False
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
return json.dumps({"modules": modules})
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
@mcp.resource('cdk-api-docs://packages/{package_name}/{module_name}/')
|
|
151
|
-
def list_module_files(package_name: str, module_name: str):
|
|
152
|
-
"""List all files in a specific module."""
|
|
153
|
-
module_dir = DOCS_DIR / "packages" / package_name / module_name
|
|
154
|
-
|
|
155
|
-
if not module_dir.exists() or not module_dir.is_dir():
|
|
156
|
-
return {"error": f"Module '{module_name}' not found in package '{package_name}'"}
|
|
157
|
-
|
|
158
|
-
# ここでのみDirectoryResourceを使用
|
|
159
|
-
return DirectoryResource(
|
|
160
|
-
uri=f"cdk-api-docs://packages/{package_name}/{module_name}/",
|
|
161
|
-
name=f"Files in {package_name}/{module_name}",
|
|
162
|
-
path=module_dir,
|
|
163
|
-
description=f"List of files in the {package_name}/{module_name} module",
|
|
164
|
-
recursive=False
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
@mcp.resource('cdk-api-docs://packages/{package_name}/{module_name}/{file_path}')
|
|
169
|
-
def get_module_file(package_name: str, module_name: str, file_path: str):
|
|
170
|
-
"""Get a specific file from a module."""
|
|
171
|
-
file_full_path = DOCS_DIR / "packages" / package_name / module_name / file_path
|
|
172
|
-
|
|
173
|
-
if not file_full_path.exists() or not file_full_path.is_file():
|
|
174
|
-
return f"Error: File '{file_path}' not found in {package_name}/{module_name}"
|
|
175
|
-
|
|
176
|
-
# Read the file content
|
|
177
|
-
with open(file_full_path, 'r', encoding='utf-8') as f:
|
|
178
|
-
content = f.read()
|
|
179
|
-
|
|
180
|
-
# Create and return a TextResource
|
|
181
|
-
return TextResource(
|
|
182
|
-
uri=f"cdk-api-docs://packages/{package_name}/{module_name}/{file_path}",
|
|
183
|
-
name=file_path,
|
|
184
|
-
text=content,
|
|
185
|
-
description=f"Documentation file: {file_path} in {package_name}/{module_name}",
|
|
186
|
-
mime_type="text/markdown" if file_path.endswith(".md") else "text/plain"
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
# Register integration tests resources
|
|
191
|
-
@mcp.resource('cdk-api-integ-tests://')
|
|
192
|
-
def list_integ_test_modules():
|
|
193
|
-
"""List all modules with integration tests."""
|
|
194
|
-
if not INTEG_TESTS_DIR.exists():
|
|
195
|
-
return {"error": "Integration tests directory not found"}
|
|
196
|
-
|
|
197
|
-
modules = []
|
|
198
|
-
for item in INTEG_TESTS_DIR.iterdir():
|
|
199
|
-
if item.is_dir():
|
|
200
|
-
modules.append({
|
|
201
|
-
"name": item.name,
|
|
202
|
-
"uri": f"cdk-api-integ-tests://{item.name}/",
|
|
203
|
-
"is_directory": True
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
return json.dumps({"modules": modules})
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
@mcp.resource('cdk-api-integ-tests://{module_name}/')
|
|
210
|
-
def list_module_tests(module_name: str):
|
|
211
|
-
"""List all integration tests for a specific module."""
|
|
212
|
-
module_dir = INTEG_TESTS_DIR / module_name
|
|
213
|
-
|
|
214
|
-
if not module_dir.exists() or not module_dir.is_dir():
|
|
215
|
-
return {"error": f"Module '{module_name}' not found in integration tests"}
|
|
216
|
-
|
|
217
|
-
# ここでのみDirectoryResourceを使用
|
|
218
|
-
return DirectoryResource(
|
|
219
|
-
uri=f"cdk-api-integ-tests://{module_name}/",
|
|
220
|
-
name=f"Integration tests for {module_name}",
|
|
221
|
-
path=module_dir,
|
|
222
|
-
description=f"List of integration tests for the {module_name} module",
|
|
223
|
-
recursive=False
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
@mcp.resource('cdk-api-integ-tests://{module_name}/{file_path}')
|
|
228
|
-
def get_module_test(module_name: str, file_path: str):
|
|
229
|
-
"""Get a specific integration test file."""
|
|
230
|
-
file_full_path = INTEG_TESTS_DIR / module_name / file_path
|
|
231
|
-
|
|
232
|
-
if not file_full_path.exists() or not file_full_path.is_file():
|
|
233
|
-
return f"Error: Integration test '{file_path}' not found for module '{module_name}'"
|
|
234
|
-
|
|
235
|
-
# Read the file content
|
|
236
|
-
with open(file_full_path, 'r', encoding='utf-8') as f:
|
|
237
|
-
content = f.read()
|
|
238
|
-
|
|
239
|
-
# Create and return a TextResource
|
|
240
|
-
return TextResource(
|
|
241
|
-
uri=f"cdk-api-integ-tests://{module_name}/{file_path}",
|
|
242
|
-
name=file_path,
|
|
243
|
-
text=content,
|
|
244
|
-
description=f"Integration test: {file_path} for {module_name}",
|
|
245
|
-
mime_type="text/markdown" if file_path.endswith(".md") else "text/plain"
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
def main():
|
|
250
|
-
"""Run the MCP server with CLI argument support."""
|
|
251
|
-
mcp.run()
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if __name__ == '__main__':
|
|
255
|
-
main()
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: konokenj.cdk-api-mcp-server
|
|
3
|
-
Version: 0.0.1
|
|
4
|
-
Summary: An MCP server provides AWS CDK API Reference
|
|
5
|
-
Project-URL: Documentation, https://github.com/konokenj/cdk-api-mcp-server#readme
|
|
6
|
-
Project-URL: Issues, https://github.com/konokenj/cdk-api-mcp-server/issues
|
|
7
|
-
Project-URL: Source, https://github.com/konokenj/cdk-api-mcp-server
|
|
8
|
-
Author-email: Kenji Kono <konoken@amazon.co.jp>
|
|
9
|
-
License-Expression: MIT
|
|
10
|
-
License-File: LICENSE.txt
|
|
11
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: Programming Language :: Python
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
|
-
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
20
|
-
Requires-Python: >=3.8
|
|
21
|
-
Requires-Dist: fastmcp>=2.0.0
|
|
22
|
-
Requires-Dist: pydantic>=2.10.6
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
|
|
25
|
-
# cdk-api-mcp-server
|
|
26
|
-
|
|
27
|
-
[](https://pypi.org/project/cdk-api-mcp-server)
|
|
28
|
-
[](https://pypi.org/project/cdk-api-mcp-server)
|
|
29
|
-
|
|
30
|
-
-----
|
|
31
|
-
|
|
32
|
-
## Table of Contents
|
|
33
|
-
|
|
34
|
-
- [Installation](#installation)
|
|
35
|
-
- [License](#license)
|
|
36
|
-
|
|
37
|
-
## Installation
|
|
38
|
-
|
|
39
|
-
```console
|
|
40
|
-
pip install cdk-api-mcp-server
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## License
|
|
44
|
-
|
|
45
|
-
`cdk-api-mcp-server` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
cdk_api_mcp_server/__about__.py,sha256=YDFhVrJ6IAPLvkmnNQeYbddiqs-wE-itcAwTO84Lt2U,128
|
|
2
|
-
cdk_api_mcp_server/__init__.py,sha256=NEvU-xodn9HlOjf2mMHp_TfU-_2UkrV6zJRJSy5vt74,169
|
|
3
|
-
cdk_api_mcp_server/server.py,sha256=XAG7UI1_Uy0F5Ff9qoL2z3FhLt5C9he39oHjhEYPhc4,157
|
|
4
|
-
cdk_api_mcp_server/core/__init__.py,sha256=vDq0hUSCu3Tfj4EJyp5p40Ak5W68S4y_NkN5Z3pKAkA,42
|
|
5
|
-
cdk_api_mcp_server/core/resources.py,sha256=yG0MPNAIYmnXioV3lSI3T1QkeelX5l83MddsbzKCZvs,4723
|
|
6
|
-
cdk_api_mcp_server/core/server.py,sha256=KgCycgr7Yxnx4JeZHIk7oG1pz7YaXc1TOva9CclM5B4,8513
|
|
7
|
-
cdk_api_mcp_server/resources/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
konokenj_cdk_api_mcp_server-0.0.1.dist-info/METADATA,sha256=y6E_ViH9EUcZMI0kvT7xz7grYG78aURNGUzGX1Aefr4,1601
|
|
9
|
-
konokenj_cdk_api_mcp_server-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
-
konokenj_cdk_api_mcp_server-0.0.1.dist-info/entry_points.txt,sha256=bVDhMdyCC1WNMPOMbmB82jvWII2CIrwTZDygdCf0cYQ,79
|
|
11
|
-
konokenj_cdk_api_mcp_server-0.0.1.dist-info/licenses/LICENSE.txt,sha256=5OIAASeg1HM22mVZ1enz9bgZ7TlsGfWXnj02P9OgFyk,1098
|
|
12
|
-
konokenj_cdk_api_mcp_server-0.0.1.dist-info/RECORD,,
|
{konokenj_cdk_api_mcp_server-0.0.1.dist-info → konokenj_cdk_api_mcp_server-0.2.0.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|