fedramp-20x-mcp 0.4.8__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.
- fedramp_20x_mcp/__init__.py +14 -0
- fedramp_20x_mcp/__main__.py +12 -0
- fedramp_20x_mcp/data_loader.py +673 -0
- fedramp_20x_mcp/prompts/__init__.py +62 -0
- fedramp_20x_mcp/prompts/api_design_guide.txt +432 -0
- fedramp_20x_mcp/prompts/ato_package_checklist.txt +75 -0
- fedramp_20x_mcp/prompts/audit_preparation.txt +592 -0
- fedramp_20x_mcp/prompts/authorization_boundary_review.txt +76 -0
- fedramp_20x_mcp/prompts/azure_ksi_automation.txt +997 -0
- fedramp_20x_mcp/prompts/continuous_monitoring_setup.txt +61 -0
- fedramp_20x_mcp/prompts/documentation_generator.txt +499 -0
- fedramp_20x_mcp/prompts/gap_analysis.txt +25 -0
- fedramp_20x_mcp/prompts/initial_assessment_roadmap.txt +202 -0
- fedramp_20x_mcp/prompts/ksi_implementation_priorities.txt +283 -0
- fedramp_20x_mcp/prompts/migration_from_rev5.txt +440 -0
- fedramp_20x_mcp/prompts/quarterly_review_checklist.txt +231 -0
- fedramp_20x_mcp/prompts/significant_change_assessment.txt +50 -0
- fedramp_20x_mcp/prompts/vendor_evaluation.txt +349 -0
- fedramp_20x_mcp/prompts/vulnerability_remediation_timeline.txt +45 -0
- fedramp_20x_mcp/server.py +270 -0
- fedramp_20x_mcp/templates/__init__.py +75 -0
- fedramp_20x_mcp/templates/bicep/afr.txt +33 -0
- fedramp_20x_mcp/templates/bicep/cna.txt +48 -0
- fedramp_20x_mcp/templates/bicep/generic.txt +47 -0
- fedramp_20x_mcp/templates/bicep/iam.txt +211 -0
- fedramp_20x_mcp/templates/bicep/mla.txt +82 -0
- fedramp_20x_mcp/templates/bicep/rpl.txt +44 -0
- fedramp_20x_mcp/templates/bicep/svc.txt +54 -0
- fedramp_20x_mcp/templates/code/generic_csharp.txt +65 -0
- fedramp_20x_mcp/templates/code/generic_powershell.txt +65 -0
- fedramp_20x_mcp/templates/code/generic_python.txt +63 -0
- fedramp_20x_mcp/templates/code/iam_csharp.txt +150 -0
- fedramp_20x_mcp/templates/code/iam_powershell.txt +162 -0
- fedramp_20x_mcp/templates/code/iam_python.txt +224 -0
- fedramp_20x_mcp/templates/code/mla_python.txt +124 -0
- fedramp_20x_mcp/templates/terraform/afr.txt +29 -0
- fedramp_20x_mcp/templates/terraform/cna.txt +50 -0
- fedramp_20x_mcp/templates/terraform/generic.txt +40 -0
- fedramp_20x_mcp/templates/terraform/iam.txt +219 -0
- fedramp_20x_mcp/templates/terraform/mla.txt +29 -0
- fedramp_20x_mcp/templates/terraform/rpl.txt +32 -0
- fedramp_20x_mcp/templates/terraform/svc.txt +46 -0
- fedramp_20x_mcp/tools/__init__.py +167 -0
- fedramp_20x_mcp/tools/definitions.py +154 -0
- fedramp_20x_mcp/tools/documentation.py +155 -0
- fedramp_20x_mcp/tools/enhancements.py +2256 -0
- fedramp_20x_mcp/tools/evidence.py +701 -0
- fedramp_20x_mcp/tools/export.py +753 -0
- fedramp_20x_mcp/tools/ksi.py +90 -0
- fedramp_20x_mcp/tools/requirements.py +163 -0
- fedramp_20x_mcp-0.4.8.dist-info/METADATA +877 -0
- fedramp_20x_mcp-0.4.8.dist-info/RECORD +55 -0
- fedramp_20x_mcp-0.4.8.dist-info/WHEEL +4 -0
- fedramp_20x_mcp-0.4.8.dist-info/entry_points.txt +2 -0
- fedramp_20x_mcp-0.4.8.dist-info/licenses/LICENSE +27 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FedRAMP 20x MCP Server - Tools Module
|
|
3
|
+
|
|
4
|
+
This module organizes all MCP tool functions into logical groups.
|
|
5
|
+
Each submodule contains related tools that are registered with the MCP server.
|
|
6
|
+
"""
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from mcp.server.fastmcp import FastMCP
|
|
13
|
+
from ..data_loader import FedRAMPDataLoader
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def register_tools(mcp: "FastMCP", data_loader: "FedRAMPDataLoader"):
|
|
19
|
+
"""
|
|
20
|
+
Register all tool functions with the MCP server.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
mcp: The FastMCP server instance
|
|
24
|
+
data_loader: The data loader instance for accessing FedRAMP data
|
|
25
|
+
"""
|
|
26
|
+
# Import all tool modules
|
|
27
|
+
from . import requirements, definitions, ksi, documentation, export, enhancements, evidence
|
|
28
|
+
from ..templates import get_infrastructure_template, get_code_template
|
|
29
|
+
|
|
30
|
+
# Requirements tools
|
|
31
|
+
@mcp.tool()
|
|
32
|
+
async def get_control(control_id: str) -> str:
|
|
33
|
+
"""Get detailed information about a specific FedRAMP 20x requirement."""
|
|
34
|
+
return await requirements.get_control_impl(control_id, data_loader)
|
|
35
|
+
|
|
36
|
+
@mcp.tool()
|
|
37
|
+
async def list_family_controls(family: str) -> str:
|
|
38
|
+
"""List all requirements within a specific document family."""
|
|
39
|
+
return await requirements.list_family_controls_impl(family, data_loader)
|
|
40
|
+
|
|
41
|
+
@mcp.tool()
|
|
42
|
+
async def search_requirements(keywords: str) -> str:
|
|
43
|
+
"""Search for FedRAMP 20x requirements containing specific keywords."""
|
|
44
|
+
return await requirements.search_requirements_impl(keywords, data_loader)
|
|
45
|
+
|
|
46
|
+
# Definition tools
|
|
47
|
+
@mcp.tool()
|
|
48
|
+
async def get_definition(term: str) -> str:
|
|
49
|
+
"""Get the FedRAMP definition for a specific term."""
|
|
50
|
+
return await definitions.get_definition_impl(term, data_loader)
|
|
51
|
+
|
|
52
|
+
@mcp.tool()
|
|
53
|
+
async def list_definitions() -> str:
|
|
54
|
+
"""List all FedRAMP definitions with their terms."""
|
|
55
|
+
return await definitions.list_definitions_impl(data_loader)
|
|
56
|
+
|
|
57
|
+
@mcp.tool()
|
|
58
|
+
async def search_definitions(keywords: str) -> str:
|
|
59
|
+
"""Search FedRAMP definitions by keywords."""
|
|
60
|
+
return await definitions.search_definitions_impl(keywords, data_loader)
|
|
61
|
+
|
|
62
|
+
# KSI tools
|
|
63
|
+
@mcp.tool()
|
|
64
|
+
async def get_ksi(ksi_id: str) -> str:
|
|
65
|
+
"""Get detailed information about a specific Key Security Indicator."""
|
|
66
|
+
return await ksi.get_ksi_impl(ksi_id, data_loader)
|
|
67
|
+
|
|
68
|
+
@mcp.tool()
|
|
69
|
+
async def list_ksi() -> str:
|
|
70
|
+
"""List all Key Security Indicators."""
|
|
71
|
+
return await ksi.list_ksi_impl(data_loader)
|
|
72
|
+
|
|
73
|
+
# Documentation tools
|
|
74
|
+
@mcp.tool()
|
|
75
|
+
async def search_documentation(keywords: str) -> str:
|
|
76
|
+
"""Search FedRAMP official documentation by keywords."""
|
|
77
|
+
return await documentation.search_documentation_impl(keywords, data_loader)
|
|
78
|
+
|
|
79
|
+
@mcp.tool()
|
|
80
|
+
async def get_documentation_file(file_path: str) -> str:
|
|
81
|
+
"""Get the full content of a specific FedRAMP documentation file."""
|
|
82
|
+
return await documentation.get_documentation_file_impl(file_path, data_loader)
|
|
83
|
+
|
|
84
|
+
@mcp.tool()
|
|
85
|
+
async def list_documentation_files() -> str:
|
|
86
|
+
"""List all available FedRAMP documentation files."""
|
|
87
|
+
return await documentation.list_documentation_files_impl(data_loader)
|
|
88
|
+
|
|
89
|
+
# Export tools
|
|
90
|
+
@mcp.tool()
|
|
91
|
+
async def export_to_excel(export_type: str, output_path: str = "") -> str:
|
|
92
|
+
"""Export FedRAMP 20x data to Excel format."""
|
|
93
|
+
return await export.export_to_excel(export_type, output_path)
|
|
94
|
+
|
|
95
|
+
@mcp.tool()
|
|
96
|
+
async def export_to_csv(export_type: str, output_path: str = "") -> str:
|
|
97
|
+
"""Export FedRAMP 20x data to CSV format."""
|
|
98
|
+
return await export.export_to_csv(export_type, output_path)
|
|
99
|
+
|
|
100
|
+
@mcp.tool()
|
|
101
|
+
async def generate_ksi_specification(ksi_id: str, evidence_collection_strategy: str, output_path: str = "") -> str:
|
|
102
|
+
"""Generate a detailed product specification document for a KSI."""
|
|
103
|
+
return await export.generate_ksi_specification(ksi_id, evidence_collection_strategy, output_path)
|
|
104
|
+
|
|
105
|
+
# Enhancement tools
|
|
106
|
+
@mcp.tool()
|
|
107
|
+
async def compare_with_rev4(requirement_area: str) -> str:
|
|
108
|
+
"""Compare FedRAMP 20x requirements to Rev 4/Rev 5 to understand changes."""
|
|
109
|
+
return await enhancements.compare_with_rev4_impl(requirement_area, data_loader)
|
|
110
|
+
|
|
111
|
+
@mcp.tool()
|
|
112
|
+
async def get_implementation_examples(requirement_id: str) -> str:
|
|
113
|
+
"""Get practical implementation examples for a requirement."""
|
|
114
|
+
return await enhancements.get_implementation_examples_impl(requirement_id, data_loader)
|
|
115
|
+
|
|
116
|
+
@mcp.tool()
|
|
117
|
+
async def check_requirement_dependencies(requirement_id: str) -> str:
|
|
118
|
+
"""Show which requirements are related or dependent on a specific requirement."""
|
|
119
|
+
return await enhancements.check_requirement_dependencies_impl(requirement_id, data_loader)
|
|
120
|
+
|
|
121
|
+
@mcp.tool()
|
|
122
|
+
async def estimate_implementation_effort(requirement_id: str) -> str:
|
|
123
|
+
"""Provide rough effort estimates for implementing a specific requirement."""
|
|
124
|
+
return await enhancements.estimate_implementation_effort_impl(requirement_id, data_loader)
|
|
125
|
+
|
|
126
|
+
@mcp.tool()
|
|
127
|
+
async def get_cloud_native_guidance(technology: str) -> str:
|
|
128
|
+
"""Get cloud-native specific guidance for implementing FedRAMP 20x."""
|
|
129
|
+
return await enhancements.get_cloud_native_guidance_impl(technology, data_loader)
|
|
130
|
+
|
|
131
|
+
@mcp.tool()
|
|
132
|
+
async def validate_architecture(architecture_description: str) -> str:
|
|
133
|
+
"""Validate a cloud architecture against FedRAMP 20x requirements."""
|
|
134
|
+
return await enhancements.validate_architecture_impl(architecture_description, data_loader)
|
|
135
|
+
|
|
136
|
+
@mcp.tool()
|
|
137
|
+
async def generate_implementation_questions(requirement_id: str) -> str:
|
|
138
|
+
"""Generate strategic questions for PMs and engineers about implementing a requirement."""
|
|
139
|
+
return await enhancements.generate_implementation_questions_impl(requirement_id, data_loader)
|
|
140
|
+
|
|
141
|
+
@mcp.tool()
|
|
142
|
+
async def get_ksi_implementation_matrix(ksi_family: str) -> str:
|
|
143
|
+
"""Get implementation matrix showing all KSIs in a family with Azure services, effort, and priority."""
|
|
144
|
+
return await enhancements.get_ksi_implementation_matrix_impl(ksi_family, data_loader)
|
|
145
|
+
|
|
146
|
+
@mcp.tool()
|
|
147
|
+
async def generate_implementation_checklist(ksi_id: str) -> str:
|
|
148
|
+
"""Generate actionable step-by-step implementation checklist for a specific KSI."""
|
|
149
|
+
return await enhancements.generate_implementation_checklist_impl(ksi_id, data_loader)
|
|
150
|
+
|
|
151
|
+
# Evidence automation tools
|
|
152
|
+
@mcp.tool()
|
|
153
|
+
async def get_infrastructure_code_for_ksi(ksi_id: str, infrastructure_type: str = "bicep") -> str:
|
|
154
|
+
"""Generate infrastructure code templates for automating KSI evidence collection."""
|
|
155
|
+
return await evidence.get_infrastructure_code_for_ksi_impl(ksi_id, data_loader, get_infrastructure_template, infrastructure_type)
|
|
156
|
+
|
|
157
|
+
@mcp.tool()
|
|
158
|
+
async def get_evidence_collection_code(ksi_id: str, language: str = "python") -> str:
|
|
159
|
+
"""Provide code examples for collecting KSI evidence programmatically."""
|
|
160
|
+
return await evidence.get_evidence_collection_code_impl(ksi_id, data_loader, get_code_template, language)
|
|
161
|
+
|
|
162
|
+
@mcp.tool()
|
|
163
|
+
async def get_evidence_automation_architecture(ksi_category: str = "all") -> str:
|
|
164
|
+
"""Provide comprehensive architecture guidance for automated evidence collection."""
|
|
165
|
+
return await evidence.get_evidence_automation_architecture_impl(data_loader, ksi_category)
|
|
166
|
+
|
|
167
|
+
logger.info("Registered 26 tools across 7 modules")
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FedRAMP 20x MCP Server - Definitions Tools
|
|
3
|
+
|
|
4
|
+
This module contains tool implementation functions for definitions.
|
|
5
|
+
"""
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
async def get_definition_impl(term: str, data_loader) -> str:
|
|
13
|
+
"""
|
|
14
|
+
Get the FedRAMP definition for a specific term.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
term: The term to look up (e.g., "vulnerability", "agency", "cloud service offering")
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Definition with notes and references if available
|
|
21
|
+
"""
|
|
22
|
+
try:
|
|
23
|
+
# Ensure data is loaded
|
|
24
|
+
await data_loader.load_data()
|
|
25
|
+
|
|
26
|
+
# Get the definition
|
|
27
|
+
definition = data_loader.get_definition(term)
|
|
28
|
+
|
|
29
|
+
if not definition:
|
|
30
|
+
return f"No FedRAMP definition found for term: '{term}'. Try searching with search_definitions() to find related terms."
|
|
31
|
+
|
|
32
|
+
# Format the definition
|
|
33
|
+
result = f"# FedRAMP Definition: {definition.get('term', term)}\n\n"
|
|
34
|
+
|
|
35
|
+
# Add ID
|
|
36
|
+
if "id" in definition:
|
|
37
|
+
result += f"**ID:** {definition['id']}\n\n"
|
|
38
|
+
|
|
39
|
+
# Add definition
|
|
40
|
+
if "definition" in definition:
|
|
41
|
+
result += f"**Definition:**\n{definition['definition']}\n\n"
|
|
42
|
+
|
|
43
|
+
# Add alternatives
|
|
44
|
+
if "alts" in definition and definition["alts"]:
|
|
45
|
+
result += f"**Also known as:** {', '.join(definition['alts'])}\n\n"
|
|
46
|
+
|
|
47
|
+
# Add notes
|
|
48
|
+
if "note" in definition:
|
|
49
|
+
result += f"**Note:**\n{definition['note']}\n\n"
|
|
50
|
+
elif "notes" in definition and isinstance(definition["notes"], list):
|
|
51
|
+
result += "**Notes:**\n"
|
|
52
|
+
for note in definition["notes"]:
|
|
53
|
+
result += f"- {note}\n"
|
|
54
|
+
result += "\n"
|
|
55
|
+
|
|
56
|
+
# Add references
|
|
57
|
+
if "reference" in definition:
|
|
58
|
+
ref_url = definition.get("reference_url", "")
|
|
59
|
+
if ref_url:
|
|
60
|
+
result += f"**Reference:** [{definition['reference']}]({ref_url})\n\n"
|
|
61
|
+
else:
|
|
62
|
+
result += f"**Reference:** {definition['reference']}\n\n"
|
|
63
|
+
|
|
64
|
+
return result
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
logger.error(f"Error fetching definition for '{term}': {e}")
|
|
68
|
+
return f"Error retrieving definition for '{term}': {str(e)}"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def list_definitions_impl(data_loader) -> str:
|
|
73
|
+
"""
|
|
74
|
+
List all FedRAMP definitions with their terms.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Complete list of FedRAMP definition terms
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
# Ensure data is loaded
|
|
81
|
+
await data_loader.load_data()
|
|
82
|
+
|
|
83
|
+
# Get all definitions
|
|
84
|
+
definitions = data_loader.list_all_definitions()
|
|
85
|
+
|
|
86
|
+
if not definitions:
|
|
87
|
+
return "No FedRAMP definitions found."
|
|
88
|
+
|
|
89
|
+
# Sort by ID
|
|
90
|
+
sorted_defs = sorted(definitions, key=lambda x: x.get("id", ""))
|
|
91
|
+
|
|
92
|
+
# Format the results
|
|
93
|
+
result = f"# FedRAMP Definitions\n\n"
|
|
94
|
+
result += f"Total: {len(definitions)} definitions\n\n"
|
|
95
|
+
|
|
96
|
+
for definition in sorted_defs:
|
|
97
|
+
def_id = definition.get("id", "Unknown")
|
|
98
|
+
term = definition.get("term", "No term")
|
|
99
|
+
result += f"- **{def_id}**: {term}\n"
|
|
100
|
+
|
|
101
|
+
result += "\n*Use get_definition(term) to see full details for any term.*\n"
|
|
102
|
+
|
|
103
|
+
return result
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
logger.error(f"Error listing definitions: {e}")
|
|
107
|
+
return f"Error retrieving definitions: {str(e)}"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
async def search_definitions_impl(keywords: str, data_loader) -> str:
|
|
112
|
+
"""
|
|
113
|
+
Search FedRAMP definitions by keywords.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
keywords: Keywords to search for in definitions
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Matching definitions with terms and brief descriptions
|
|
120
|
+
"""
|
|
121
|
+
try:
|
|
122
|
+
# Ensure data is loaded
|
|
123
|
+
await data_loader.load_data()
|
|
124
|
+
|
|
125
|
+
# Search definitions
|
|
126
|
+
definitions = data_loader.search_definitions(keywords)
|
|
127
|
+
|
|
128
|
+
if not definitions:
|
|
129
|
+
return f"No definitions found matching keywords: '{keywords}'"
|
|
130
|
+
|
|
131
|
+
# Format the results
|
|
132
|
+
result = f"# Definition Search Results for: '{keywords}'\n\n"
|
|
133
|
+
result += f"Found {len(definitions)} matching definitions:\n\n"
|
|
134
|
+
|
|
135
|
+
for definition in definitions[:20]:
|
|
136
|
+
def_id = definition.get("id", "Unknown")
|
|
137
|
+
term = definition.get("term", "No term")
|
|
138
|
+
def_text = definition.get("definition", "")
|
|
139
|
+
|
|
140
|
+
result += f"## {def_id}: {term}\n"
|
|
141
|
+
|
|
142
|
+
# Show a snippet
|
|
143
|
+
if def_text:
|
|
144
|
+
snippet = def_text[:150] + "..." if len(def_text) > 150 else def_text
|
|
145
|
+
result += f"{snippet}\n\n"
|
|
146
|
+
|
|
147
|
+
if len(definitions) > 20:
|
|
148
|
+
result += f"\n*Showing first 20 of {len(definitions)} results.*\n"
|
|
149
|
+
|
|
150
|
+
return result
|
|
151
|
+
|
|
152
|
+
except Exception as e:
|
|
153
|
+
logger.error(f"Error searching definitions for '{keywords}': {e}")
|
|
154
|
+
return f"Error searching definitions for '{keywords}': {str(e)}"
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FedRAMP 20x MCP Server - Documentation Tools
|
|
3
|
+
|
|
4
|
+
This module contains tool implementation functions for documentation.
|
|
5
|
+
"""
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
async def search_documentation_impl(keywords: str, data_loader) -> str:
|
|
13
|
+
"""
|
|
14
|
+
Search FedRAMP documentation markdown files for specific keywords.
|
|
15
|
+
|
|
16
|
+
This searches the official FedRAMP documentation from https://github.com/FedRAMP/docs/tree/main/docs
|
|
17
|
+
including guides, overviews, and detailed documentation for each standard.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
keywords: Keywords to search for in the documentation
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Matching documentation sections with context
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
# Ensure documentation is loaded
|
|
27
|
+
await data_loader.load_documentation()
|
|
28
|
+
|
|
29
|
+
# Search documentation
|
|
30
|
+
results = data_loader.search_documentation(keywords)
|
|
31
|
+
|
|
32
|
+
if not results:
|
|
33
|
+
return f"No documentation found matching '{keywords}'.\n\nTry:\n- Different keywords\n- More general terms\n- list_documentation_files() to see all available docs"
|
|
34
|
+
|
|
35
|
+
result = f"# Documentation Search Results for '{keywords}'\n\n"
|
|
36
|
+
result += f"Found {len(results)} matches across FedRAMP documentation.\n\n"
|
|
37
|
+
|
|
38
|
+
# Group results by file
|
|
39
|
+
by_file: Dict[str, List[Dict[str, Any]]] = {}
|
|
40
|
+
for match in results:
|
|
41
|
+
filename = match['filename']
|
|
42
|
+
if filename not in by_file:
|
|
43
|
+
by_file[filename] = []
|
|
44
|
+
by_file[filename].append(match)
|
|
45
|
+
|
|
46
|
+
# Show results grouped by file (limit to first 10 files)
|
|
47
|
+
for filename in list(by_file.keys())[:10]:
|
|
48
|
+
matches = by_file[filename]
|
|
49
|
+
result += f"## {filename}\n\n"
|
|
50
|
+
result += f"{len(matches)} match(es) found\n\n"
|
|
51
|
+
|
|
52
|
+
# Show first 3 matches from this file
|
|
53
|
+
for match in matches[:3]:
|
|
54
|
+
result += f"**Line {match['line_number']}:**\n"
|
|
55
|
+
result += f"```\n{match['context']}\n```\n\n"
|
|
56
|
+
|
|
57
|
+
if len(matches) > 3:
|
|
58
|
+
result += f"*...and {len(matches) - 3} more matches in this file*\n\n"
|
|
59
|
+
|
|
60
|
+
if len(by_file) > 10:
|
|
61
|
+
result += f"\n*Showing first 10 of {len(by_file)} files with matches. Refine your search for more specific results.*\n"
|
|
62
|
+
|
|
63
|
+
result += "\n**Tip:** Use `get_documentation_file(filename)` to read the full content of any file.\n"
|
|
64
|
+
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
except Exception as e:
|
|
68
|
+
logger.error(f"Error searching documentation for '{keywords}': {e}")
|
|
69
|
+
return f"Error searching documentation: {str(e)}"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
async def get_documentation_file_impl(filename: str, data_loader) -> str:
|
|
74
|
+
"""
|
|
75
|
+
Get the full content of a specific FedRAMP documentation file.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
filename: The markdown filename (e.g., "overview.md", "key-security-indicators.md")
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Full markdown content of the documentation file
|
|
82
|
+
"""
|
|
83
|
+
try:
|
|
84
|
+
# Ensure documentation is loaded
|
|
85
|
+
await data_loader.load_documentation()
|
|
86
|
+
|
|
87
|
+
# Get the file content
|
|
88
|
+
content = data_loader.get_documentation_file(filename)
|
|
89
|
+
|
|
90
|
+
if not content:
|
|
91
|
+
available = data_loader.list_documentation_files()
|
|
92
|
+
return f"Documentation file '{filename}' not found.\n\n**Available files:**\n" + '\n'.join(f"- {f}" for f in available)
|
|
93
|
+
|
|
94
|
+
result = f"# {filename}\n\n"
|
|
95
|
+
result += content
|
|
96
|
+
|
|
97
|
+
return result
|
|
98
|
+
|
|
99
|
+
except Exception as e:
|
|
100
|
+
logger.error(f"Error fetching documentation file '{filename}': {e}")
|
|
101
|
+
return f"Error retrieving documentation file: {str(e)}"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def list_documentation_files_impl(data_loader) -> str:
|
|
106
|
+
"""
|
|
107
|
+
List all available FedRAMP documentation files.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
List of all markdown documentation files from https://github.com/FedRAMP/docs/tree/main/docs
|
|
111
|
+
"""
|
|
112
|
+
try:
|
|
113
|
+
# Ensure documentation is loaded
|
|
114
|
+
await data_loader.load_documentation()
|
|
115
|
+
|
|
116
|
+
# Get list of files
|
|
117
|
+
files = data_loader.list_documentation_files()
|
|
118
|
+
|
|
119
|
+
if not files:
|
|
120
|
+
return "No documentation files found."
|
|
121
|
+
|
|
122
|
+
result = "# Available FedRAMP Documentation Files\n\n"
|
|
123
|
+
result += f"**Total:** {len(files)} files\n\n"
|
|
124
|
+
|
|
125
|
+
# Group by type
|
|
126
|
+
standards = [f for f in files if f not in ['overview.md', 'guidelines.md', 'index.md'] and not f.startswith('20x') and not f.startswith('rev5')]
|
|
127
|
+
guides = [f for f in files if f in ['overview.md', 'guidelines.md', 'index.md']]
|
|
128
|
+
other = [f for f in files if f not in standards and f not in guides]
|
|
129
|
+
|
|
130
|
+
if standards:
|
|
131
|
+
result += "## FedRAMP 20x Standards\n\n"
|
|
132
|
+
for f in sorted(standards):
|
|
133
|
+
result += f"- {f}\n"
|
|
134
|
+
result += "\n"
|
|
135
|
+
|
|
136
|
+
if guides:
|
|
137
|
+
result += "## General Documentation\n\n"
|
|
138
|
+
for f in sorted(guides):
|
|
139
|
+
result += f"- {f}\n"
|
|
140
|
+
result += "\n"
|
|
141
|
+
|
|
142
|
+
if other:
|
|
143
|
+
result += "## Other Documentation\n\n"
|
|
144
|
+
for f in sorted(other):
|
|
145
|
+
result += f"- {f}\n"
|
|
146
|
+
result += "\n"
|
|
147
|
+
|
|
148
|
+
result += "**Usage:** Use `get_documentation_file(filename)` to read any file's full content.\n"
|
|
149
|
+
result += "**Search:** Use `search_documentation(keywords)` to find specific information.\n"
|
|
150
|
+
|
|
151
|
+
return result
|
|
152
|
+
|
|
153
|
+
except Exception as e:
|
|
154
|
+
logger.error(f"Error listing documentation files: {e}")
|
|
155
|
+
return f"Error listing documentation files: {str(e)}"
|