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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/aws-documentation-mcp-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,42 @@ For getting started with development on the AWS Documentation MCP server, please

Unit tests: `uv run --frozen pytest --cov --cov-branch --cov-report=term-missing`
Unit tests with integration tests: `uv run --frozen pytest --cov --cov-branch --cov-report=term-missing --run-live`

## Scope

This server searches AWS documentation via the official AWS Docs Search API, and
`read_documentation` supports AWS docs plus selected additional domains.

- `search_documentation`: scoped to AWS docs search (not Kiro docs)
- `read_documentation` supports:
- `docs.aws.amazon.com` (requires `.html`)
- `awsdocs-neuron.readthedocs-hosted.com` (requires `.html`)
- `kiro.dev/docs/` (any path)

### What this server can NOT search

The `search_documentation` tool calls the official AWS Documentation Search API,
which does not index third-party or product-specific documentation sites.

| Documentation | Site | Workaround |
|---|---|---|
| Kiro IDE | `kiro.dev/docs/` | Use `read_documentation` with the direct URL |
| Kiro CLI | `kiro.dev/docs/cli/` | Use `read_documentation` with the direct URL |

### Accessing Kiro documentation

For Kiro IDE/CLI topics, skip `search_documentation` and call `read_documentation`
directly with the relevant URL:
```
# Kiro CLI custom agents
read_documentation("https://kiro.dev/docs/cli/custom-agents/creating/")

# Kiro CLI MCP configuration
read_documentation("https://kiro.dev/docs/cli/mcp/")

# Kiro CLI steering files
read_documentation("https://kiro.dev/docs/cli/steering/")

# Kiro IDE overview
read_documentation("https://kiro.dev/docs/")
```
Original file line number Diff line number Diff line change
Expand Up @@ -107,23 +107,26 @@ async def read_documentation(
ge=0,
),
) -> str:
"""Fetch and convert an AWS documentation page to markdown format.
"""Fetch and convert a documentation page to markdown format.

## Usage

This tool retrieves the content of an AWS documentation page and converts it to markdown format.
For long documents, you can make multiple calls with different start_index values to retrieve
the entire content in chunks.

Supported domains:
- AWS documentation: https://docs.aws.amazon.com/...
- Kiro IDE/CLI docs: https://kiro.dev/docs/...
- Neuron SDK docs: https://awsdocs-neuron.readthedocs-hosted.com/...

For Kiro topics not found via search_documentation, call this tool
directly with the kiro.dev URL (e.g. https://kiro.dev/docs/cli/custom-agents/creating/).

## URL Requirements

- Must be from the docs.aws.amazon.com domain
- Must end with .html
- AWS and Neuron SDK: Must end with .html
- Kiro: Any path under kiro.dev/docs/ (does not require .html)

## Example URLs

- https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html
- https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html
- https://kiro.dev/docs/cli/custom-agents/creating/

## Output Format

Expand All @@ -148,19 +151,23 @@ async def read_documentation(
Returns:
Markdown content of the AWS documentation
"""
# Validate that URL is from docs.aws.amazon.com and ends with .html
# Validate that URL is from a supported domain
url_str = str(url)

supported_domains_regex = [r'^https?://docs\.aws\.amazon\.com/']
supported_domains_regex = [
r'^https?://docs\.aws\.amazon\.com/.*\.html$',
r'^https?://kiro\.dev(:\d+)?/docs/[^?#]*$',
]
for modifier in SEARCH_TERM_DOMAIN_MODIFIERS:
supported_domains_regex.append(modifier['regex'])
# Neuron SDK pages require .html
supported_domains_regex.append(modifier['regex'] + r'.*\.html$')

if not any(re.match(domain_regex, url_str) for domain_regex in supported_domains_regex):
await ctx.error(f'Invalid URL: {url_str}. URL must be from list of supported domains')
await ctx.error(
f'Invalid URL: {url_str}. URL must be from docs.aws.amazon.com (ending in .html), '
f'kiro.dev/docs/ (any path), or awsdocs-neuron.readthedocs-hosted.com (ending in .html)'
)
raise ValueError('URL must be from list of supported domains')
if not url_str.endswith('.html'):
await ctx.error(f'Invalid URL: {url_str}. URL must end with .html')
raise ValueError('URL must end with .html')

return await read_documentation_impl(ctx, url_str, max_length, start_index, SESSION_UUID)

Expand Down Expand Up @@ -265,9 +272,20 @@ async def search_documentation(
"""Search AWS documentation using the official AWS Documentation Search API.

## Usage
This tool ONLY searches docs.aws.amazon.com. It cannot find documentation for:
- Kiro IDE or Kiro CLI (kiro.dev/docs) — these are NOT on docs.aws.amazon.com
- Any third-party or community documentation

For Kiro IDE/CLI topics (agents, MCP config, steering, hooks, autocomplete,
specs, etc.), do NOT use this search tool. Instead, call read_documentation
directly with the appropriate kiro.dev URL:
- Kiro CLI overview: https://kiro.dev/docs/cli/
- Kiro CLI custom agents: https://kiro.dev/docs/cli/custom-agents/creating/
- Kiro CLI MCP config: https://kiro.dev/docs/cli/mcp/
- Kiro CLI steering: https://kiro.dev/docs/cli/steering/
- Kiro CLI hooks: https://kiro.dev/docs/cli/hooks/
- Kiro IDE overview: https://kiro.dev/docs/

This tool searches across all AWS documentation for pages matching your search phrase.
Use it to find relevant documentation when you don't have a specific URL.

## Search Tips

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,23 @@ async def read_documentation(

## Usage

This tool retrieves the content of an AWS China documentation page and converts it to markdown format.
For long documents, you can make multiple calls with different start_index values to retrieve
the entire content in chunks.
Supported domains:
- AWS China documentation: https://docs.amazonaws.cn/...
- Kiro IDE/CLI docs: https://kiro.dev/docs/...

For Kiro IDE/CLI topics, call this tool directly with the kiro.dev URL,
e.g. https://kiro.dev/docs/cli/custom-agents/creating/

## URL Requirements

- Must be from the docs.amazonaws.cn domain
- Must end with .html
- AWS China docs: Must end with .html
- Kiro docs: Any path under kiro.dev/docs/ (does not require .html)

## Example URLs

- https://docs.amazonaws.cn/en_us/AmazonS3/latest/userguide/bucketnamingrules.html
- https://docs.amazonaws.cn/en_us/lambda/latest/dg/lambda-invocation.html
- https://kiro.dev/docs/cli/custom-agents/creating/

## Output Format

Expand All @@ -120,14 +124,18 @@ async def read_documentation(
Returns:
Markdown content of the AWS China documentation
"""
# Validate that URL is from docs.amazonaws.cn and ends with .html
# Validate that URL is from a supported domain
url_str = str(url)
if not re.match(r'^https?://docs\.amazonaws\.cn/', url_str):
error_msg = f'Invalid URL: {url_str}. URL must be from the docs.amazonaws.cn domain'
await ctx.error(error_msg)
return error_msg
if not url_str.endswith('.html'):
error_msg = f'Invalid URL: {url_str}. URL must end with .html'

# Check if URL matches AWS China documentation or Kiro documentation
is_valid_aws_cn = re.match(r'^https?://docs\.amazonaws\.cn/.*\.html$', url_str)
is_valid_kiro = re.match(r'^https?://kiro\.dev(:\d+)?/docs/.*$', url_str)

if not (is_valid_aws_cn or is_valid_kiro):
error_msg = (
f'Invalid URL: {url_str}. URL must be from docs.amazonaws.cn (ending in .html) '
f'or kiro.dev/docs/ (any path)'
)
await ctx.error(error_msg)
return error_msg

Expand Down
15 changes: 14 additions & 1 deletion src/aws-documentation-mcp-server/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,25 @@ def pytest_addoption(parser):
def pytest_configure(config):
"""Configure pytest."""
config.addinivalue_line('markers', 'live: mark test as making live API calls')
config.addinivalue_line(
'markers', 'requires_uv: mark test as requiring uv package manager'
)


def pytest_collection_modifyitems(config, items):
"""Skip live tests unless --run-live is specified."""
"""Skip live tests unless --run-live is specified, and skip requires_uv tests if uv is unavailable."""
import shutil

uv_available = shutil.which('uv') is not None

if not config.getoption('--run-live'):
skip_live = pytest.mark.skip(reason='need --run-live option to run')
for item in items:
if 'live' in item.keywords:
item.add_marker(skip_live)

if not uv_available:
skip_uv = pytest.mark.skip(reason="Requires 'uv' package manager to be installed")
for item in items:
if 'requires_uv' in item.keywords:
item.add_marker(skip_uv)
Loading