Coverage for gco_mcp / resources / docs.py: 100.00%

371 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-09-14 22:07 +0000

1"""Documentation resources (docs:// scheme) for the GCO MCP server.""" 

2 

3import re 

4from pathlib import Path 

5 

6from cli_runner import PROJECT_ROOT # runtime-resolved checkout root (uvx-safe) 

7from server import mcp 

8 

9DOCS_DIR = PROJECT_ROOT / "docs" 

10EXAMPLES_DIR = PROJECT_ROOT / "examples" 

11ADR_DIR = DOCS_DIR / "adr" 

12 

13# --------------------------------------------------------------------------- 

14# Example metadata — used by both the index and the per-example resource to 

15# give the LLM rich context about what each manifest does and how to adapt it. 

16# --------------------------------------------------------------------------- 

17 

18EXAMPLE_METADATA: dict[str, dict[str, str | list[str]]] = { 

19 "simple-job": { 

20 "category": "Jobs & Training", 

21 "summary": "Basic Kubernetes Job that runs a command and completes. Start here to verify your cluster.", 

22 "gpu": "no", 

23 "opt_in": "", 

24 "submission": "gco jobs submit-sqs examples/simple-job.yaml --region us-east-1", 

25 "keywords": ["simple", "hello", "starter", "basic", "smoke test"], 

26 "instance_types": [], 

27 "use_cases": [ 

28 "verify cluster setup", 

29 "smoke test a new region", 

30 "minimal job example", 

31 ], 

32 "related": ["gpu-job", "sqs-job-submission"], 

33 }, 

34 "gpu-job": { 

35 "category": "Jobs & Training", 

36 "summary": "Requests GPU resources and runs on GPU-enabled nodes.", 

37 "gpu": "NVIDIA", 

38 "opt_in": "", 

39 "submission": "gco jobs submit-sqs examples/gpu-job.yaml --region us-east-1", 

40 "keywords": [ 

41 "gpu", 

42 "nvidia", 

43 "cuda", 

44 "single gpu", 

45 "nvidia.com/gpu", 

46 "g5", 

47 "g6", 

48 "g4dn", 

49 "tolerations", 

50 ], 

51 "instance_types": ["g5.xlarge", "g6.xlarge", "g4dn.xlarge"], 

52 "use_cases": [ 

53 "run a single GPU workload", 

54 "test GPU node provisioning", 

55 "smoke test CUDA", 

56 ], 

57 "related": ["multi-gpu-training", "simple-job"], 

58 }, 

59 "multi-gpu-training": { 

60 "category": "Jobs & Training", 

61 "summary": "PyTorch DistributedDataParallel (DDP) across multiple GPUs with indexed pods and headless service.", 

62 "gpu": "NVIDIA", 

63 "opt_in": "", 

64 "submission": "kubectl apply -f examples/multi-gpu-training.yaml", 

65 "keywords": [ 

66 "ddp", 

67 "distributed", 

68 "pytorch", 

69 "multi gpu", 

70 "training", 

71 "torchrun", 

72 "nccl", 

73 "indexed pods", 

74 "headless service", 

75 ], 

76 "instance_types": ["g5.12xlarge", "g6.12xlarge", "p4d.24xlarge"], 

77 "use_cases": [ 

78 "distributed PyTorch DDP training", 

79 "scale a training job across multiple GPUs", 

80 ], 

81 "related": ["gpu-job", "efa-distributed-training", "trainium-job"], 

82 }, 

83 "efa-distributed-training": { 

84 "category": "Jobs & Training", 

85 "summary": "Elastic Fabric Adapter (EFA) for high-bandwidth inter-node communication (up to 3.2 Tbps on P5, 28.8 Tbps on P6e). For p4d/p5/p5e/p5en/p6-b200/p6-b300/p6e-gb200/trn instances.", 

86 "gpu": "NVIDIA + EFA", 

87 "opt_in": "", 

88 "submission": "gco jobs submit-direct examples/efa-distributed-training.yaml -r us-east-1", 

89 "keywords": ["efa", "elastic fabric adapter", "distributed", "nccl", "high bandwidth"], 

90 "instance_types": [ 

91 "p4d.24xlarge", 

92 "p5.48xlarge", 

93 "trn1.32xlarge", 

94 "trn2.48xlarge", 

95 ], 

96 "use_cases": [ 

97 "multi-node distributed training over EFA", 

98 "high-bandwidth NCCL all-reduce", 

99 "large-scale model pretraining", 

100 ], 

101 "related": ["multi-gpu-training", "trainium-job", "gpu-job"], 

102 }, 

103 "kubeflow-trainjob": { 

104 "category": "Jobs & Training", 

105 "summary": "Kubeflow Trainer v2 TrainJob: 2-node distributed PyTorch through the torch-distributed runtime (CPU-sized; GPU variant documented via runtimePatches).", 

106 "gpu": "no", 

107 "opt_in": "", 

108 "submission": "gco jobs submit-sqs examples/kubeflow-trainjob.yaml --region us-east-1", 

109 "keywords": [ 

110 "kubeflow", 

111 "trainer", 

112 "trainjob", 

113 "torchrun", 

114 "distributed training", 

115 "jobset", 

116 "gang scheduling", 

117 "pytorch", 

118 ], 

119 "instance_types": [], 

120 "use_cases": [ 

121 "multi-node training through the TrainJob API", 

122 "distributed PyTorch without writing JobSets", 

123 "gang-schedule training via the Kueue default queue", 

124 ], 

125 "related": ["multi-gpu-training", "efa-distributed-training", "kueue-job"], 

126 }, 

127 "mlflow-tracking-job": { 

128 "category": "Jobs & Training", 

129 "summary": "Logs params and a loss curve to the in-cluster MLflow tracking server over service DNS, then reads the run back and asserts every value round-tripped.", 

130 "gpu": "no", 

131 "opt_in": "", 

132 "submission": "gco jobs submit-direct examples/mlflow-tracking-job.yaml -r us-east-1", 

133 "keywords": [ 

134 "mlflow", 

135 "experiment tracking", 

136 "metrics", 

137 "tracking server", 

138 "runs", 

139 "observability", 

140 ], 

141 "instance_types": [], 

142 "use_cases": [ 

143 "track training runs in MLflow", 

144 "log metrics from a job", 

145 "verify the tracking pipeline end to end", 

146 ], 

147 "related": ["kubeflow-trainjob", "multi-gpu-training"], 

148 }, 

149 "model-download-job": { 

150 "category": "Jobs & Training", 

151 "summary": "Pre-downloads HuggingFace model weights to shared EFS for inference endpoints.", 

152 "gpu": "no", 

153 "opt_in": "", 

154 "submission": "kubectl apply -f examples/model-download-job.yaml", 

155 "keywords": ["huggingface", "download", "weights", "model cache", "efs"], 

156 "instance_types": [], 

157 "use_cases": [ 

158 "stage HuggingFace weights on EFS", 

159 "warm a model cache before serving", 

160 ], 

161 "related": ["inference-vllm", "inference-tgi", "efs-output-job"], 

162 }, 

163 "sqs-job-submission": { 

164 "category": "Jobs & Training", 

165 "summary": "Demonstrates SQS-based submission (recommended). Contains CPU and GPU job examples.", 

166 "gpu": "optional", 

167 "opt_in": "", 

168 "submission": "gco jobs submit-sqs examples/sqs-job-submission.yaml --region us-east-1", 

169 "keywords": ["sqs", "submission", "queue", "broker"], 

170 "instance_types": [], 

171 "use_cases": [ 

172 "submit jobs through the SQS queue", 

173 "queue-based job submission pattern", 

174 ], 

175 "related": ["simple-job", "gpu-job", "keda-scaled-job"], 

176 }, 

177 "trainium-job": { 

178 "category": "Accelerator Jobs", 

179 "summary": "AWS Trainium instance with Neuron SDK. Lower cost than GPU for training.", 

180 "gpu": "Trainium", 

181 "opt_in": "", 

182 "submission": "gco jobs submit examples/trainium-job.yaml --region us-east-1", 

183 "keywords": ["trainium", "neuron", "trn1", "trn2", "training accelerator"], 

184 "instance_types": ["trn1.2xlarge", "trn1.32xlarge", "trn2.48xlarge"], 

185 "use_cases": [ 

186 "lower-cost training on AWS silicon", 

187 "train with the Neuron SDK", 

188 ], 

189 "related": ["inferentia-job", "efa-distributed-training"], 

190 }, 

191 "inferentia-job": { 

192 "category": "Accelerator Jobs", 

193 "summary": "AWS Inferentia2 with Neuron SDK. Optimized for low-cost, high-throughput inference.", 

194 "gpu": "Inferentia", 

195 "opt_in": "", 

196 "submission": "gco jobs submit examples/inferentia-job.yaml --region us-east-1", 

197 "keywords": ["inferentia", "neuron", "inf2", "inference accelerator"], 

198 "instance_types": ["inf2.xlarge", "inf2.8xlarge", "inf2.24xlarge", "inf2.48xlarge"], 

199 "use_cases": [ 

200 "low-cost inference on AWS silicon", 

201 "high-throughput batch inference", 

202 ], 

203 "related": ["trainium-job", "inference-vllm"], 

204 }, 

205 "inference-vllm": { 

206 "category": "Inference Serving", 

207 "summary": "vLLM OpenAI-compatible LLM serving with PagedAttention.", 

208 "gpu": "NVIDIA", 

209 "opt_in": "", 

210 "submission": "gco inference deploy my-llm -i vllm/vllm-openai:v0.29.0 --gpu-count 1", 

211 "keywords": [ 

212 "vllm", 

213 "openai", 

214 "openai-compatible", 

215 "llm serving", 

216 "pagedattention", 

217 "inference", 

218 "completions", 

219 "chat completions", 

220 "v1/chat/completions", 

221 "model server", 

222 "llama", 

223 "qwen", 

224 "mistral", 

225 ], 

226 "instance_types": ["g5.xlarge", "g5.12xlarge", "g6.xlarge"], 

227 "use_cases": [ 

228 "serve an LLM with an OpenAI-compatible API", 

229 "high-throughput LLM inference", 

230 "deploy a chat completions endpoint", 

231 ], 

232 "related": ["inference-tgi", "inference-sglang", "inference-triton", "model-download-job"], 

233 }, 

234 "inference-tgi": { 

235 "category": "Inference Serving", 

236 "summary": "HuggingFace Text Generation Inference — optimized transformer serving.", 

237 "gpu": "NVIDIA", 

238 "opt_in": "", 

239 "submission": "gco jobs submit-direct examples/inference-tgi.yaml -r us-east-1", 

240 "keywords": ["tgi", "huggingface", "text generation", "llm serving"], 

241 "instance_types": ["g5.xlarge", "g5.12xlarge", "g6.xlarge"], 

242 "use_cases": [ 

243 "serve HuggingFace LLMs with TGI", 

244 "transformer text-generation endpoint", 

245 ], 

246 "related": ["inference-vllm", "inference-sglang", "inference-torchserve"], 

247 }, 

248 "inference-triton": { 

249 "category": "Inference Serving", 

250 "summary": "NVIDIA Triton Inference Server — multi-framework (PyTorch, TensorFlow, ONNX).", 

251 "gpu": "NVIDIA", 

252 "opt_in": "", 

253 "submission": "gco jobs submit-direct examples/inference-triton.yaml -r us-east-1", 

254 "keywords": ["triton", "nvidia", "multi-framework", "onnx", "tensorflow", "inference"], 

255 "instance_types": ["g5.xlarge", "g6.xlarge"], 

256 "use_cases": [ 

257 "multi-framework inference serving", 

258 "serve ONNX or TensorFlow models", 

259 ], 

260 "related": ["inference-vllm", "inference-torchserve"], 

261 }, 

262 "inference-torchserve": { 

263 "category": "Inference Serving", 

264 "summary": "PyTorch TorchServe model serving.", 

265 "gpu": "NVIDIA", 

266 "opt_in": "", 

267 "submission": "gco jobs submit-direct examples/inference-torchserve.yaml -r us-east-1", 

268 "keywords": ["torchserve", "pytorch", "model serving"], 

269 "instance_types": ["g5.xlarge", "g6.xlarge"], 

270 "use_cases": [ 

271 "serve a PyTorch model with TorchServe", 

272 ], 

273 "related": ["inference-triton", "inference-vllm"], 

274 }, 

275 "inference-sglang": { 

276 "category": "Inference Serving", 

277 "summary": "SGLang high-throughput serving with RadixAttention for prefix caching.", 

278 "gpu": "NVIDIA", 

279 "opt_in": "", 

280 "submission": "gco jobs submit-direct examples/inference-sglang.yaml -r us-east-1", 

281 "keywords": ["sglang", "radixattention", "prefix caching", "llm serving"], 

282 "instance_types": ["g5.xlarge", "g5.12xlarge"], 

283 "use_cases": [ 

284 "high-throughput LLM serving with prefix caching", 

285 "serve LLMs with structured output", 

286 ], 

287 "related": ["inference-vllm", "inference-tgi"], 

288 }, 

289 "efs-output-job": { 

290 "category": "Storage & Persistence", 

291 "summary": "Writes output to shared EFS storage. Results persist after pod termination.", 

292 "gpu": "no", 

293 "opt_in": "", 

294 "submission": "gco jobs submit-direct examples/efs-output-job.yaml --region us-east-1 -n gco-jobs", 

295 "keywords": ["efs", "shared storage", "persistent", "output"], 

296 "instance_types": [], 

297 "use_cases": [ 

298 "persist job output to EFS", 

299 "share data between pods via EFS", 

300 ], 

301 "related": ["fsx-lustre-job", "model-download-job", "cluster-shared-bucket-upload-job"], 

302 }, 

303 "fsx-lustre-job": { 

304 "category": "Storage & Persistence", 

305 "summary": "FSx for Lustre high-performance parallel storage (1000+ GB/s throughput).", 

306 "gpu": "no", 

307 "opt_in": "FSx (gco stacks fsx enable -y)", 

308 "submission": "gco jobs submit-direct examples/fsx-lustre-job.yaml --region us-east-1 -n gco-jobs", 

309 "keywords": ["fsx", "lustre", "parallel storage", "high throughput", "hpc"], 

310 "instance_types": [], 

311 "use_cases": [ 

312 "high-throughput parallel storage for training", 

313 "stream large datasets to GPU nodes", 

314 ], 

315 "related": ["efs-output-job", "multi-gpu-training", "efa-distributed-training"], 

316 }, 

317 "valkey-cache-job": { 

318 "category": "Caching & Databases", 

319 "summary": "Valkey Serverless cache for K/V caching, prompt caching, session state, feature stores.", 

320 "gpu": "no", 

321 "opt_in": 'Valkey ("valkey": {"enabled": true} in cdk.json)', 

322 "submission": "gco jobs submit-direct examples/valkey-cache-job.yaml -r us-east-1", 

323 "keywords": ["valkey", "redis", "cache", "kv store", "session state"], 

324 "instance_types": [], 

325 "use_cases": [ 

326 "cache prompts or session state", 

327 "use Valkey from a job", 

328 "feature store backed by Valkey", 

329 ], 

330 "related": ["aurora-pgvector-job"], 

331 }, 

332 "aurora-pgvector-job": { 

333 "category": "Caching & Databases", 

334 "summary": "Aurora Serverless v2 PostgreSQL with pgvector for RAG and semantic search.", 

335 "gpu": "no", 

336 "opt_in": 'Aurora ("aurora_pgvector": {"enabled": true} in cdk.json)', 

337 "submission": "gco jobs submit-direct examples/aurora-pgvector-job.yaml -r us-east-1", 

338 "keywords": ["aurora", "pgvector", "postgres", "rag", "vector database", "embeddings"], 

339 "instance_types": [], 

340 "use_cases": [ 

341 "RAG with pgvector", 

342 "semantic search backed by Postgres", 

343 "store embeddings in Aurora", 

344 ], 

345 "related": ["valkey-cache-job", "analytics-database-export-job"], 

346 }, 

347 "vector-store-search-job": { 

348 "category": "Caching & Databases", 

349 "summary": "Read-only semantic search against the built-in DynamoDB vector store: Bedrock query embedding + SearchVectors against the local replica, asserting at least one hit.", 

350 "gpu": "no", 

351 "opt_in": 'Vector store ("vector_store": {"enabled": true} in cdk.json)', 

352 "submission": "gco jobs submit-direct examples/vector-store-search-job.yaml -r us-east-1", 

353 "keywords": [ 

354 "vector store", 

355 "dynamodb", 

356 "semantic search", 

357 "embeddings", 

358 "bedrock", 

359 "searchvectors", 

360 "rag", 

361 ], 

362 "instance_types": [], 

363 "use_cases": [ 

364 "semantic search over the ingested corpus", 

365 "RAG retrieval from a job", 

366 "query the vector store from workloads", 

367 ], 

368 "related": ["aurora-pgvector-job", "valkey-cache-job"], 

369 }, 

370 "cluster-shared-bucket-upload-job": { 

371 "category": "Storage & Persistence", 

372 "summary": "Uploads a file to the always-on Cluster_Shared_Bucket using the gco-cluster-shared-bucket ConfigMap via envFrom. Works with analytics disabled.", 

373 "gpu": "no", 

374 "opt_in": "", 

375 "submission": "gco jobs submit-direct examples/cluster-shared-bucket-upload-job.yaml -r us-east-1", 

376 "keywords": ["s3", "shared bucket", "upload", "configmap"], 

377 "instance_types": [], 

378 "use_cases": [ 

379 "upload artifacts to the shared S3 bucket", 

380 "share files across regions via S3", 

381 ], 

382 "related": [ 

383 "efs-output-job", 

384 "analytics-s3-upload-job", 

385 "regional-shared-bucket-upload-job", 

386 ], 

387 }, 

388 "regional-shared-bucket-upload-job": { 

389 "category": "Storage & Persistence", 

390 "summary": "Uploads a file to the always-on Regional_Shared_Bucket using the gco-regional-shared-bucket ConfigMap via envFrom. Same-region as the cluster, so no cross-region egress — the right target for training checkpoints.", 

391 "gpu": "no", 

392 "opt_in": "", 

393 "submission": "gco jobs submit-direct examples/regional-shared-bucket-upload-job.yaml -r us-east-1", 

394 "keywords": [ 

395 "s3", 

396 "regional bucket", 

397 "checkpoint", 

398 "upload", 

399 "configmap", 

400 "same-region", 

401 ], 

402 "instance_types": [], 

403 "use_cases": [ 

404 "write training checkpoints to S3 from a job", 

405 "upload artifacts without cross-region egress", 

406 "persist job outputs to the region's own bucket", 

407 ], 

408 "related": ["cluster-shared-bucket-upload-job", "efs-output-job"], 

409 }, 

410 "analytics-s3-upload-job": { 

411 "category": "Analytics", 

412 "summary": "Publishes a dataset snapshot plus schema manifest to Cluster_Shared_Bucket under analytics-data/ so a SageMaker Studio notebook can read it.", 

413 "gpu": "no", 

414 "opt_in": 'Analytics ("analytics_environment": {"enabled": true} in cdk.json)', 

415 "submission": "gco jobs submit-direct examples/analytics-s3-upload-job.yaml -r us-east-1", 

416 "keywords": ["analytics", "s3", "sagemaker", "dataset", "schema"], 

417 "instance_types": [], 

418 "use_cases": [ 

419 "publish a dataset for a SageMaker Studio notebook", 

420 "share an analytics snapshot via S3", 

421 ], 

422 "related": ["analytics-database-export-job", "cluster-shared-bucket-upload-job"], 

423 }, 

424 "analytics-database-export-job": { 

425 "category": "Analytics", 

426 "summary": "Exports rows from the regional Aurora pgvector cluster to Cluster_Shared_Bucket as CSV for a SageMaker Studio notebook to analyse.", 

427 "gpu": "no", 

428 "opt_in": 'Aurora + Analytics ("aurora_pgvector.enabled" and "analytics_environment.enabled" in cdk.json)', 

429 "submission": "gco jobs submit-direct examples/analytics-database-export-job.yaml -r us-east-1", 

430 "keywords": ["analytics", "aurora", "csv", "export", "sagemaker"], 

431 "instance_types": [], 

432 "use_cases": [ 

433 "export Aurora rows to S3 as CSV", 

434 "feed a SageMaker Studio notebook from Postgres", 

435 ], 

436 "related": ["aurora-pgvector-job", "analytics-s3-upload-job"], 

437 }, 

438 "volcano-gang-job": { 

439 "category": "Schedulers", 

440 "summary": "Volcano gang scheduling — all pods scheduled together or none. Master + workers topology.", 

441 "gpu": "no", 

442 "opt_in": "", 

443 "submission": "kubectl apply -f examples/volcano-gang-job.yaml", 

444 "keywords": ["volcano", "gang scheduling", "batch", "scheduler"], 

445 "instance_types": [], 

446 "use_cases": [ 

447 "schedule all pods at once or none", 

448 "MPI-style master + workers topology", 

449 ], 

450 "related": ["kueue-job", "yunikorn-job", "slurm-cluster-job"], 

451 }, 

452 "kueue-job": { 

453 "category": "Schedulers", 

454 "summary": "Kueue job queueing with ClusterQueue, LocalQueue, ResourceFlavors, and fair-sharing.", 

455 "gpu": "optional", 

456 "opt_in": "", 

457 "submission": "kubectl apply -f examples/kueue-job.yaml", 

458 "keywords": ["kueue", "queueing", "fair sharing", "scheduler", "clusterqueue"], 

459 "instance_types": [], 

460 "use_cases": [ 

461 "queue jobs with quotas and fair sharing", 

462 "multi-tenant batch scheduling", 

463 ], 

464 "related": ["volcano-gang-job", "yunikorn-job"], 

465 }, 

466 "yunikorn-job": { 

467 "category": "Schedulers", 

468 "summary": "Apache YuniKorn app-aware scheduling with hierarchical queues and gang scheduling.", 

469 "gpu": "no", 

470 "opt_in": 'YuniKorn ("helm": {"yunikorn": {"enabled": true}} in cdk.json)', 

471 "submission": "kubectl apply -f examples/yunikorn-job.yaml", 

472 "keywords": ["yunikorn", "scheduler", "hierarchical queues", "gang scheduling"], 

473 "instance_types": [], 

474 "use_cases": [ 

475 "app-aware scheduling with hierarchical queues", 

476 "YuniKorn-style gang scheduling", 

477 ], 

478 "related": ["kueue-job", "volcano-gang-job"], 

479 }, 

480 "keda-scaled-job": { 

481 "category": "Schedulers", 

482 "summary": "KEDA ScaledJob — custom SQS-triggered autoscaling. Template for custom consumers.", 

483 "gpu": "no", 

484 "opt_in": "", 

485 "submission": "kubectl apply -f examples/keda-scaled-job.yaml", 

486 "keywords": ["keda", "scaledjob", "autoscaling", "sqs", "event driven"], 

487 "instance_types": [], 

488 "use_cases": [ 

489 "scale jobs from SQS queue depth", 

490 "event-driven job autoscaling", 

491 ], 

492 "related": ["sqs-job-submission"], 

493 }, 

494 "slurm-cluster-job": { 

495 "category": "Schedulers", 

496 "summary": "Slinky Slurm Operator — sbatch submission on Kubernetes for HPC workloads.", 

497 "gpu": "no", 

498 "opt_in": 'Slurm ("helm": {"slurm": {"enabled": true}} in cdk.json)', 

499 "submission": "kubectl apply -f examples/slurm-cluster-job.yaml", 

500 "keywords": ["slurm", "hpc", "sbatch", "slinky"], 

501 "instance_types": [], 

502 "use_cases": [ 

503 "submit sbatch jobs on Kubernetes", 

504 "run HPC workloads with Slurm", 

505 ], 

506 "related": ["volcano-gang-job"], 

507 }, 

508 "ray-cluster": { 

509 "category": "Distributed Computing", 

510 "summary": "KubeRay RayCluster for distributed training, tuning, and serving. Auto-scaling workers.", 

511 "gpu": "no", 

512 "opt_in": "", 

513 "submission": "kubectl apply -f examples/ray-cluster.yaml", 

514 "keywords": ["ray", "kuberay", "distributed", "tune", "serve"], 

515 "instance_types": [], 

516 "use_cases": [ 

517 "stand up a Ray cluster on EKS", 

518 "distributed training and tuning with Ray", 

519 ], 

520 "related": ["multi-gpu-training", "pipeline-dag"], 

521 }, 

522 "pipeline-dag": { 

523 "category": "DAG Pipelines", 

524 "summary": "Multi-step pipeline with dependency ordering. Preprocess → Train via shared EFS.", 

525 "gpu": "no", 

526 "opt_in": "", 

527 "submission": "gco dag run examples/pipeline-dag.yaml -r us-east-1", 

528 "keywords": ["dag", "pipeline", "workflow", "dependencies"], 

529 "instance_types": [], 

530 "use_cases": [ 

531 "run a multi-step ML pipeline", 

532 "chain preprocess and train jobs", 

533 ], 

534 "related": ["dag-step-preprocess", "dag-step-train", "ray-cluster"], 

535 }, 

536 "dag-step-preprocess": { 

537 "category": "DAG Pipelines", 

538 "summary": "DAG step 1: generates training data on shared EFS.", 

539 "gpu": "no", 

540 "opt_in": "", 

541 "submission": "(used by pipeline-dag.yaml)", 

542 "keywords": ["dag", "preprocess", "step", "pipeline"], 

543 "instance_types": [], 

544 "use_cases": [ 

545 "preprocessing step of a pipeline", 

546 "generate training data for a downstream step", 

547 ], 

548 "related": ["pipeline-dag", "dag-step-train"], 

549 }, 

550 "dag-step-train": { 

551 "category": "DAG Pipelines", 

552 "summary": "DAG step 2: reads preprocess output, trains model, writes artifacts to EFS.", 

553 "gpu": "no", 

554 "opt_in": "", 

555 "submission": "(used by pipeline-dag.yaml)", 

556 "keywords": ["dag", "train", "step", "pipeline"], 

557 "instance_types": [], 

558 "use_cases": [ 

559 "training step of a pipeline", 

560 "consume preprocess output and train", 

561 ], 

562 "related": ["pipeline-dag", "dag-step-preprocess"], 

563 }, 

564} 

565 

566 

567# --------------------------------------------------------------------------- 

568# Doc metadata — used by ``find_docs`` and the docs:// discovery resources to 

569# describe every markdown file under ``docs/``. Indexed by basename without 

570# extension (e.g. ``ARCHITECTURE``). The vocabulary in ``topics`` is kept 

571# small and consistent so topic-based search across docs stays predictable. 

572# --------------------------------------------------------------------------- 

573 

574DOC_METADATA: dict[str, dict[str, str | list[str]]] = { 

575 "ANALYTICS": { 

576 "summary": "Optional SageMaker Studio + EMR Serverless analytics environment, enabled via a single cdk.json toggle.", 

577 "topics": ["analytics", "storage", "customization", "gpu"], 

578 "keywords": [ 

579 "sagemaker studio", 

580 "emr serverless", 

581 "cognito", 

582 "data science", 

583 "notebook", 

584 "presigned url", 

585 "studio domain", 

586 "analytics environment", 

587 "user pool", 

588 ], 

589 "related": ["CLUSTER_SHARED_BUCKET", "CUSTOMIZATION"], 

590 }, 

591 "API": { 

592 "summary": ( 

593 "Reference for every GCO HTTP surface: the control plane (manifests, " 

594 "jobs, queue, templates, webhooks, cost), cross-region aggregation, " 

595 "inference, health and observability, plus which paths each API " 

596 "Gateway exposes and the cluster-internal surfaces." 

597 ), 

598 "topics": ["api", "cli", "jobs", "inference", "webhooks", "templates"], 

599 "keywords": [ 

600 "rest", 

601 "manifest processor", 

602 "inference proxy", 

603 "health monitor", 

604 "endpoints", 

605 "auth", 

606 "hmac request envelope", 

607 "api gateway", 

608 "sigv4", 

609 "openapi", 

610 "submit job", 

611 "api surface", 

612 ], 

613 "related": ["CLI", "ARCHITECTURE"], 

614 }, 

615 "ARCHITECTURE": { 

616 "summary": "Deep dive into the multi-region infrastructure, security layers, data flow, and scale characteristics.", 

617 "topics": [ 

618 "architecture", 

619 "concepts", 

620 "security", 

621 "multi-region", 

622 "eks", 

623 "capacity", 

624 "inference", 

625 "gpu", 

626 "monitoring", 

627 "deployment", 

628 "nodepools", 

629 "storage", 

630 "images", 

631 "cost", 

632 "networking", 

633 ], 

634 "keywords": [ 

635 "multi-region", 

636 "eks", 

637 "vpc", 

638 "global accelerator", 

639 "data flow", 

640 "control plane", 

641 "data plane", 

642 "regional stack", 

643 "global stack", 

644 "iam", 

645 "kms", 

646 "high level design", 

647 "blast radius", 

648 ], 

649 "related": ["CONCEPTS", "CUSTOMIZATION", "API"], 

650 }, 

651 "AUTOPILOT": { 

652 "summary": ( 

653 "gco autopilot: one command to a fully configured Claude Code " 

654 "session on Amazon Bedrock with the GCO MCP server and the " 

655 "recommended companion MCP servers wired in." 

656 ), 

657 "topics": [ 

658 "cli", 

659 "mcp", 

660 "agents", 

661 "bedrock", 

662 "getting-started", 

663 "deployment", 

664 ], 

665 "keywords": [ 

666 "autopilot", 

667 "claude code", 

668 "bedrock", 

669 "mcp", 

670 "agent session", 

671 "companion servers", 

672 "feature flags", 

673 "session resume", 

674 "skills", 

675 "plugins", 

676 "dev container", 

677 "front door", 

678 ], 

679 "related": ["CLI", "CONCEPTS"], 

680 }, 

681 "CLI": { 

682 "summary": "Complete command-line interface reference for the gco CLI across jobs, queues, stacks, capacity, inference, and more.", 

683 "topics": [ 

684 "cli", 

685 "api", 

686 "jobs", 

687 "capacity", 

688 "inference", 

689 "cost", 

690 "gpu", 

691 "multi-region", 

692 "images", 

693 "nodepools", 

694 "deployment", 

695 ], 

696 "keywords": [ 

697 "gco", 

698 "command-line", 

699 "subcommand", 

700 "submit job", 

701 "stacks deploy", 

702 "stacks destroy", 

703 "capacity status", 

704 "ai_recommend", 

705 "reserve_capacity", 

706 "images build", 

707 "models upload", 

708 ], 

709 "related": ["API", "RUNBOOKS"], 

710 }, 

711 "CLUSTER_SHARED_BUCKET": { 

712 "summary": "Reference for the always-on Cluster_Shared_Bucket — the S3 bucket every regional cluster can read and write by default.", 

713 "topics": ["storage", "concepts", "multi-region", "security"], 

714 "keywords": [ 

715 "s3", 

716 "shared bucket", 

717 "cross-region", 

718 "configmap", 

719 "envFrom", 

720 "kms", 

721 "iam grant", 

722 "bucket policy", 

723 "always-on", 

724 ], 

725 "related": ["ANALYTICS", "ARCHITECTURE", "REGIONAL_SHARED_BUCKET"], 

726 }, 

727 "REGIONAL_SHARED_BUCKET": { 

728 "summary": "Reference for the always-on Regional_Shared_Bucket — the per-region S3 bucket each cluster's job pods can read and write in their own region, with no cross-region egress.", 

729 "topics": ["storage", "concepts", "security"], 

730 "keywords": [ 

731 "s3", 

732 "regional bucket", 

733 "checkpoint", 

734 "same-region", 

735 "configmap", 

736 "envFrom", 

737 "kms", 

738 "iam grant", 

739 "pod identity", 

740 "always-on", 

741 "teardown", 

742 ], 

743 "related": ["CLUSTER_SHARED_BUCKET", "ARCHITECTURE"], 

744 }, 

745 "CONCEPTS": { 

746 "summary": "Fundamental concepts behind GCO — what it is, the problems it solves, and how the key components fit together.", 

747 "topics": [ 

748 "concepts", 

749 "architecture", 

750 "multi-region", 

751 "capacity", 

752 "gpu", 

753 "eks", 

754 "jobs", 

755 "inference", 

756 ], 

757 "keywords": [ 

758 "what is gco", 

759 "fundamentals", 

760 "components", 

761 "global queue", 

762 "capacity orchestration", 

763 "ai/ml workloads", 

764 "gpu allocation", 

765 "regional clusters", 

766 ], 

767 "related": ["ARCHITECTURE", "README"], 

768 }, 

769 "COST_MONITORING": { 

770 "summary": "Cost monitoring and cost-aware scheduling — per-region OpenCost with a Grafana cost dashboard, scheduled Parquet cost reports to S3, cross-region Athena analytics, the /api/v1/cost API, and spot price-gated central-queue dispatch.", 

771 "topics": [ 

772 "cost", 

773 "monitoring", 

774 "observability", 

775 "queue", 

776 "customization", 

777 "api", 

778 "cli", 

779 ], 

780 "keywords": [ 

781 "opencost", 

782 "cost allocation", 

783 "athena", 

784 "glue", 

785 "parquet", 

786 "cost reports", 

787 "cost dashboard", 

788 "spot price", 

789 "max spot price", 

790 "cost-aware scheduling", 

791 "namespace cost", 

792 "finops", 

793 ], 

794 "related": ["MONITORING", "CUSTOMIZATION", "API"], 

795 }, 

796 "CUSTOMIZATION": { 

797 "summary": "How to customize GCO — deployment regions, EKS configuration, GPU nodepools, and more.", 

798 "topics": [ 

799 "customization", 

800 "architecture", 

801 "gpu", 

802 "eks", 

803 "nodepools", 

804 "storage", 

805 "multi-region", 

806 "deployment", 

807 ], 

808 "keywords": [ 

809 "cdk.json", 

810 "regions", 

811 "addons", 

812 "instance types", 

813 "fsx", 

814 "valkey", 

815 "aurora", 

816 "feature toggles", 

817 "queue processor", 

818 "helm charts", 

819 "image registry config", 

820 ], 

821 "related": ["ARCHITECTURE", "ANALYTICS"], 

822 }, 

823 "DISTRIBUTED_TRAINING": { 

824 "summary": ( 

825 "Multi-node distributed training through the Kubeflow Trainer v2 " 

826 "TrainJob API — runtimes, validation semantics, GPU variants, " 

827 "Kueue gang scheduling, and Spot guidance." 

828 ), 

829 "topics": [ 

830 "jobs", 

831 "gpu", 

832 "schedulers", 

833 "architecture", 

834 ], 

835 "keywords": [ 

836 "kubeflow", 

837 "trainer", 

838 "trainjob", 

839 "distributed training", 

840 "torchrun", 

841 "jobset", 

842 "clustertrainingruntime", 

843 "gang scheduling", 

844 "pytorchjob", 

845 "spot", 

846 ], 

847 "related": ["KUEUE", "SCHEDULERS", "MONITORING", "CUSTOMIZATION"], 

848 }, 

849 "FLOCI_TESTING": { 

850 "summary": ( 

851 "Emulated-AWS test layer between in-process mocks and real-account " 

852 "live validation: production code issuing genuine SDK requests " 

853 "against a Floci emulator in CI, with zero AWS credentials." 

854 ), 

855 "topics": [ 

856 "ci", 

857 "deployment", 

858 "security", 

859 "automation", 

860 ], 

861 "keywords": [ 

862 "floci", 

863 "emulator", 

864 "localstack alternative", 

865 "integration tests", 

866 "aws endpoint url", 

867 "emulated aws", 

868 "gco release validate", 

869 "emulator endpoint", 

870 "wire protocol", 

871 "test layers", 

872 "known emulator gaps", 

873 ], 

874 "related": ["LIVE_RELEASE_VALIDATION", "CLI", "MAINTENANCE"], 

875 }, 

876 "FORKING": { 

877 "summary": ( 

878 "Take GCO into your own repository: repoint badges, clone URLs, the " 

879 "GitHub Pages site, and the OIDC trust-policy subject with " 

880 "scripts/migrate_fork.py, plus the follow-ups it cannot decide." 

881 ), 

882 "topics": ["forking", "migration", "repository", "ci", "oidc"], 

883 "keywords": [ 

884 "fork", 

885 "migrate", 

886 "own repository", 

887 "rename repo", 

888 "badges", 

889 "oidc trust policy", 

890 "github pages", 

891 "codeowners", 

892 "solution id", 

893 "upstream remote", 

894 ], 

895 "related": ["CUSTOMIZATION", "MAINTENANCE"], 

896 }, 

897 "IMAGE_MIRROR": { 

898 "summary": "Mirror third-party container images (chiefly Volcano's docker.io images) into the project's gco/* ECR so the cluster pulls from same-account ECR instead of a rate-limited upstream.", 

899 "topics": ["images", "customization", "deployment", "eks", "schedulers"], 

900 "keywords": [ 

901 "ecr", 

902 "mirror", 

903 "docker hub", 

904 "docker.io", 

905 "volcano", 

906 "pull-through cache", 

907 "multi-arch", 

908 "image_registry", 

909 "rate limit", 

910 "skopeo", 

911 "buildx", 

912 ], 

913 "related": ["VOLCANO", "CUSTOMIZATION"], 

914 }, 

915 "INFERENCE": { 

916 "summary": "Deploy and manage multi-region GPU inference endpoints, including model weight management and supported frameworks.", 

917 "topics": [ 

918 "inference", 

919 "architecture", 

920 "gpu", 

921 "multi-region", 

922 "cost", 

923 "images", 

924 "monitoring", 

925 ], 

926 "keywords": [ 

927 "vllm", 

928 "tgi", 

929 "triton", 

930 "torchserve", 

931 "sglang", 

932 "endpoints", 

933 "canary", 

934 "rolling update", 

935 "model weights", 

936 "global accelerator", 

937 "openai-compatible", 

938 "inference monitor", 

939 ], 

940 "related": ["ARCHITECTURE", "RUNBOOKS"], 

941 }, 

942 "KEDA": { 

943 "summary": "KEDA event-driven autoscaling integration — scales workloads from external sources like SQS, Kafka, and Prometheus.", 

944 "topics": ["schedulers", "jobs", "autoscaling"], 

945 "keywords": [ 

946 "keda", 

947 "scaledjob", 

948 "scaledobject", 

949 "sqs trigger", 

950 "event-driven", 

951 "kafka", 

952 "prometheus", 

953 "queue depth", 

954 ], 

955 "related": ["SCHEDULERS", "VOLCANO"], 

956 }, 

957 "KUBERAY": { 

958 "summary": "KubeRay operator integration — runs Ray distributed computing workloads on Kubernetes for training, tuning, and serving.", 

959 "topics": ["schedulers", "jobs", "gpu", "training", "distributed"], 

960 "keywords": [ 

961 "kuberay", 

962 "ray", 

963 "raycluster", 

964 "rayjob", 

965 "rayservice", 

966 "ray tune", 

967 "ray train", 

968 "ray serve", 

969 "distributed", 

970 ], 

971 "related": ["SCHEDULERS", "VOLCANO"], 

972 }, 

973 "KUEUE": { 

974 "summary": "Kueue integration for Kubernetes-native job queueing with resource quotas, fair sharing, and priority scheduling.", 

975 "topics": ["schedulers", "jobs"], 

976 "keywords": [ 

977 "kueue", 

978 "clusterqueue", 

979 "localqueue", 

980 "resourceflavor", 

981 "quota", 

982 "fair sharing", 

983 "priority", 

984 "preemption", 

985 ], 

986 "related": ["SCHEDULERS", "VOLCANO", "YUNIKORN"], 

987 }, 

988 "LEARNING_PATH": { 

989 "summary": "Staged, hands-on onboarding path for users new to GCO or Kubernetes — a Kubernetes primer, cost-boundary milestones, and role-based tracks that sequence the other guides.", 

990 "topics": [ 

991 "concepts", 

992 "quickstart", 

993 "cli", 

994 "jobs", 

995 "inference", 

996 "schedulers", 

997 ], 

998 "keywords": [ 

999 "learning path", 

1000 "onboarding", 

1001 "getting started", 

1002 "tutorial", 

1003 "curriculum", 

1004 "new user", 

1005 "beginner", 

1006 "kubernetes", 

1007 "first job", 

1008 "role based", 

1009 ], 

1010 "related": ["CONCEPTS", "CLI", "SCHEDULERS"], 

1011 }, 

1012 "LIVE_RELEASE_VALIDATION": { 

1013 "summary": "Local operator deploy-test-destroy harness for exact-commit live validation, guaranteed cleanup, and manually attached pull request reports.", 

1014 "topics": [ 

1015 "deployment", 

1016 "runbooks", 

1017 "security", 

1018 "automation", 

1019 "multi-region", 

1020 ], 

1021 "keywords": [ 

1022 "live release validation", 

1023 "local script", 

1024 "dedicated validation account", 

1025 "exact commit", 

1026 "deploy test destroy", 

1027 "checkpoint", 

1028 "resume", 

1029 "kms pending deletion", 

1030 "manual pull request upload", 

1031 "pull request comment", 

1032 ], 

1033 "related": ["RUNBOOKS", "MAINTENANCE", "CLI", "EXAMPLE_VALIDATION"], 

1034 }, 

1035 "EXAMPLE_VALIDATION": { 

1036 "summary": "Deploy-run-destroy validation of every shipped example manifest through its documented submission path, plus the offline static checks CI enforces on any examples/ change.", 

1037 "topics": [ 

1038 "deployment", 

1039 "runbooks", 

1040 "jobs", 

1041 "examples", 

1042 "automation", 

1043 ], 

1044 "keywords": [ 

1045 "example validation", 

1046 "examples", 

1047 "gco examples validate", 

1048 "static checks", 

1049 "documented submission path", 

1050 "kubectl tunnel", 

1051 "per-example report", 

1052 "disclosed mutations", 

1053 "capacity skip", 

1054 "feature enabled overrides", 

1055 ], 

1056 "related": ["LIVE_RELEASE_VALIDATION", "CLI", "KUBERAY", "KUEUE", "SLURM_OPERATOR"], 

1057 }, 

1058 "MAINTENANCE": { 

1059 "summary": "Routine upkeep — adding instance types to the nodepool lists, EKS Kubernetes version upgrades, base-image security-epoch refreshes, CVE-suppression renewals, and acting on the monthly dependency scan.", 

1060 "topics": [ 

1061 "customization", 

1062 "deployment", 

1063 "eks", 

1064 "nodepools", 

1065 "images", 

1066 ], 

1067 "keywords": [ 

1068 "maintenance", 

1069 "upkeep", 

1070 "upgrade", 

1071 "eks version", 

1072 "kubernetes version", 

1073 "instance types", 

1074 "instance family", 

1075 "dependency scan", 

1076 "deps-scan", 

1077 "security epoch", 

1078 "cve suppression", 

1079 "kubectl", 

1080 "helm", 

1081 "addon versions", 

1082 "requirements-lock", 

1083 ], 

1084 "related": ["CUSTOMIZATION", "RUNBOOKS", "ARCHITECTURE"], 

1085 }, 

1086 "MISSION": { 

1087 "summary": "Goal-directed iteration loop — declare a directive, criteria, tool allowlist, and budget; runs deterministic five-phase iterations until a verdict.", 

1088 "topics": [ 

1089 "concepts", 

1090 "cli", 

1091 "api", 

1092 "automation", 

1093 "feature-flags", 

1094 ], 

1095 "keywords": [ 

1096 "mission", 

1097 "directive", 

1098 "criteria", 

1099 "verdict", 

1100 "iteration", 

1101 "goal directed", 

1102 "autonomous loop", 

1103 "sampling", 

1104 "sandbox", 

1105 "predicate", 

1106 "checkpoint", 

1107 "budget", 

1108 "final report", 

1109 ], 

1110 "related": ["CLI", "ARCHITECTURE", "RUNBOOKS"], 

1111 }, 

1112 "SWARM": { 

1113 "summary": "Swarm supervision — one orchestrator Mission session spawns and drives concurrent child Mission sessions under hard rails (fleet cap, pooled iteration budget, finite child budgets) until its deterministic cascade reaches a verdict.", 

1114 "topics": [ 

1115 "concepts", 

1116 "cli", 

1117 "api", 

1118 "automation", 

1119 "feature-flags", 

1120 ], 

1121 "keywords": [ 

1122 "swarm", 

1123 "orchestrator", 

1124 "supervisor", 

1125 "child missions", 

1126 "fleet", 

1127 "spawn", 

1128 "iteration pool", 

1129 "restart policy", 

1130 "respawn", 

1131 "children status", 

1132 "swarm plan", 

1133 "concurrency", 

1134 "gco_enable_swarm", 

1135 ], 

1136 "related": ["MISSION", "CLI", "ARCHITECTURE"], 

1137 }, 

1138 "MONITORING": { 

1139 "summary": "Self-hosted per-cluster observability (kube-prometheus-stack: Prometheus + Alertmanager + Grafana), on by default, with private port-forward access and the gco monitoring CLI.", 

1140 "topics": [ 

1141 "monitoring", 

1142 "observability", 

1143 "gpu", 

1144 "schedulers", 

1145 "cli", 

1146 "concepts", 

1147 "cost", 

1148 ], 

1149 "keywords": [ 

1150 "prometheus", 

1151 "grafana", 

1152 "alertmanager", 

1153 "kube-prometheus-stack", 

1154 "dcgm", 

1155 "servicemonitor", 

1156 "podmonitor", 

1157 "dashboards", 

1158 "port-forward", 

1159 "ssm tunnel", 

1160 "gco monitoring", 

1161 "credential rotation", 

1162 "cluster observability", 

1163 ], 

1164 "related": ["ARCHITECTURE", "RUNBOOKS", "CLI", "INFERENCE"], 

1165 }, 

1166 "README": { 

1167 "summary": "Documentation index — the top-level guide map for the rest of the docs/ tree.", 

1168 "topics": ["concepts", "multi-region", "gpu", "capacity", "inference", "quickstart"], 

1169 "keywords": [ 

1170 "index", 

1171 "overview", 

1172 "guide map", 

1173 "documentation", 

1174 "table of contents", 

1175 "getting started", 

1176 ], 

1177 "related": ["CONCEPTS", "ARCHITECTURE"], 

1178 }, 

1179 "RUNBOOKS": { 

1180 "summary": "Operational runbooks — step-by-step procedures for common operational scenarios with symptoms, diagnosis, and resolution.", 

1181 "topics": [ 

1182 "runbooks", 

1183 "troubleshooting", 

1184 "jobs", 

1185 "inference", 

1186 "capacity", 

1187 "monitoring", 

1188 "deployment", 

1189 ], 

1190 "keywords": [ 

1191 "incident response", 

1192 "operational procedures", 

1193 "stuck job", 

1194 "endpoint down", 

1195 "capacity exhausted", 

1196 "stack rollback", 

1197 "playbook", 

1198 "diagnose", 

1199 "remediation", 

1200 ], 

1201 "related": ["TROUBLESHOOTING", "CLI"], 

1202 }, 

1203 "SCHEDULERS": { 

1204 "summary": "Comparison and overview of the six supported scheduling and orchestration tools — Volcano, Kueue, KubeRay, KEDA, Slurm, YuniKorn.", 

1205 "topics": ["schedulers", "concepts", "jobs", "gpu"], 

1206 "keywords": [ 

1207 "volcano", 

1208 "kueue", 

1209 "kuberay", 

1210 "keda", 

1211 "slurm", 

1212 "yunikorn", 

1213 "gang scheduling", 

1214 "batch scheduler", 

1215 "scheduler comparison", 

1216 "queueing", 

1217 ], 

1218 "related": ["VOLCANO", "KUEUE", "KUBERAY"], 

1219 }, 

1220 "SLURM_OPERATOR": { 

1221 "summary": "Slinky Slurm Operator integration — runs sbatch, srun, and salloc inside an EKS cluster for HPC workflows.", 

1222 "topics": ["schedulers", "jobs", "hpc"], 

1223 "keywords": [ 

1224 "slurm", 

1225 "slinky", 

1226 "sbatch", 

1227 "srun", 

1228 "salloc", 

1229 "hpc", 

1230 "scientific computing", 

1231 "mpi", 

1232 ], 

1233 "related": ["SCHEDULERS", "VOLCANO"], 

1234 }, 

1235 "TROUBLESHOOTING": { 

1236 "summary": "Troubleshooting guide — common installation, deployment, kubectl, and pod issues with their resolutions.", 

1237 "topics": [ 

1238 "troubleshooting", 

1239 "runbooks", 

1240 "deployment", 

1241 "eks", 

1242 "jobs", 

1243 "inference", 

1244 "capacity", 

1245 ], 

1246 "keywords": [ 

1247 "kubectl", 

1248 "pod crashloop", 

1249 "imagepullbackoff", 

1250 "stack rollback", 

1251 "deployment failed", 

1252 "credentials", 

1253 "vpc", 

1254 "nodepool not scaling", 

1255 "common errors", 

1256 "fix", 

1257 ], 

1258 "related": ["RUNBOOKS", "CLI"], 

1259 }, 

1260 "VOLCANO": { 

1261 "summary": "Volcano batch scheduler integration — gang scheduling, fair-share queuing, and job lifecycle management for AI/ML and HPC.", 

1262 "topics": ["schedulers", "jobs", "gpu", "hpc"], 

1263 "keywords": [ 

1264 "volcano", 

1265 "gang scheduling", 

1266 "vcjob", 

1267 "podgroup", 

1268 "queue", 

1269 "fair share", 

1270 "job lifecycle", 

1271 "batch", 

1272 ], 

1273 "related": ["SCHEDULERS", "KUEUE", "YUNIKORN"], 

1274 }, 

1275 "YUNIKORN": { 

1276 "summary": "Apache YuniKorn integration — multi-tenant scheduler with hierarchical queues and gang scheduling.", 

1277 "topics": ["schedulers", "jobs"], 

1278 "keywords": [ 

1279 "yunikorn", 

1280 "hierarchical queues", 

1281 "multi-tenant", 

1282 "gang scheduling", 

1283 "app-aware scheduling", 

1284 "fair share", 

1285 ], 

1286 "related": ["SCHEDULERS", "KUEUE", "VOLCANO"], 

1287 }, 

1288} 

1289 

1290 

1291# --------------------------------------------------------------------------- 

1292# Root-doc metadata — searchable project-level guidance that deliberately lives 

1293# at the repository root rather than under ``docs/``. Keep this separate from 

1294# ``DOC_METADATA`` so the strict 1:1 metadata-to-``docs/*.md`` invariant remains 

1295# meaningful. Root docs use static ``docs://gco/{name}`` resources. 

1296# --------------------------------------------------------------------------- 

1297 

1298ROOT_DOC_METADATA: dict[str, dict[str, str | list[str]]] = { 

1299 "TENETS": { 

1300 "path": "TENETS.md", 

1301 "summary": ( 

1302 "Prioritized project tenets and north-star guidance for safety, truth, " 

1303 "security, global capacity orchestration, automation, operations, cost, " 

1304 "and maintainability." 

1305 ), 

1306 "topics": [ 

1307 "concepts", 

1308 "architecture", 

1309 "security", 

1310 "automation", 

1311 "multi-region", 

1312 "deployment", 

1313 "cost", 

1314 ], 

1315 "keywords": [ 

1316 "tenets", 

1317 "north star", 

1318 "principles", 

1319 "decision framework", 

1320 "project ethos", 

1321 "safety", 

1322 "truth", 

1323 "reversibility", 

1324 "least privilege", 

1325 "capacity policy", 

1326 "deterministic automation", 

1327 "definition of done", 

1328 ], 

1329 "related": ["ARCHITECTURE", "MAINTENANCE", "LIVE_RELEASE_VALIDATION"], 

1330 } 

1331} 

1332 

1333 

1334# --------------------------------------------------------------------------- 

1335# Package-doc metadata — used by ``find_docs`` and the 

1336# ``docs://gco/packages/...`` resources to describe the package-level READMEs 

1337# that live next to the code (under ``gco_mcp/``) rather than in ``docs/``. These 

1338# are developer-facing internals guides (how a package is structured and how to 

1339# customize it), kept in a catalog separate from ``DOC_METADATA`` so the strict 

1340# 1:1 ``docs/*.md`` invariant stays intact. Each entry is keyed by a stable 

1341# slug and carries a ``path`` relative to the project root. A ``related`` entry 

1342# may reference either another package slug or a ``DOC_METADATA`` key. 

1343# --------------------------------------------------------------------------- 

1344 

1345PACKAGE_DOC_METADATA: dict[str, dict[str, str | list[str]]] = { 

1346 "mcp-server": { 

1347 "path": "gco_mcp/README.md", 

1348 "summary": "GCO MCP server guide — setup across MCP clients, feature-flag gating, and the full tool and resource catalog.", 

1349 "topics": ["mcp", "concepts", "feature-flags", "customization"], 

1350 "keywords": [ 

1351 "mcp server", 

1352 "fastmcp", 

1353 "stdio", 

1354 "feature flags", 

1355 "gco_enable", 

1356 "kiro", 

1357 "claude desktop", 

1358 "cursor", 

1359 "tool search", 

1360 "available tools", 

1361 "resources", 

1362 ], 

1363 "related": ["mcp-tools", "mcp-resources", "CLI", "MISSION"], 

1364 }, 

1365 "mcp-tools": { 

1366 "path": "gco_mcp/tools/README.md", 

1367 "summary": "How MCP tools are defined — one module per domain, the @mcp.tool + audit_logged pattern, and how to add a new tool.", 

1368 "topics": ["mcp", "customization"], 

1369 "keywords": [ 

1370 "tool", 

1371 "mcp.tool", 

1372 "audit_logged", 

1373 "cli_runner", 

1374 "adding a tool", 

1375 "tool module", 

1376 "domain", 

1377 ], 

1378 "related": ["mcp-server", "mcp-resources"], 

1379 }, 

1380 "mcp-resources": { 

1381 "path": "gco_mcp/resources/README.md", 

1382 "summary": "MCP resource modules by URI scheme (docs://, source://, k8s://, …) and how to add a new resource group.", 

1383 "topics": ["mcp", "customization"], 

1384 "keywords": [ 

1385 "resource", 

1386 "mcp.resource", 

1387 "uri scheme", 

1388 "docs scheme", 

1389 "source scheme", 

1390 "resource index", 

1391 "adding a resource", 

1392 ], 

1393 "related": ["mcp-server", "mcp-tools"], 

1394 }, 

1395 "mcp-mission": { 

1396 "path": "gco_mcp/mission/README.md", 

1397 "summary": "Mission package internals — the five-phase goal-directed loop, deterministic verdict cascade, sandboxes, and how to extend each piece.", 

1398 "topics": ["mcp", "automation", "customization", "concepts"], 

1399 "keywords": [ 

1400 "mission", 

1401 "engine", 

1402 "verdict", 

1403 "five-phase loop", 

1404 "sandbox", 

1405 "predicate", 

1406 "sampling", 

1407 "criteria", 

1408 "customize mission", 

1409 "module map", 

1410 ], 

1411 "related": ["MISSION", "mcp-metric-readers", "mcp-mission-judge", "mcp-server"], 

1412 }, 

1413 "mcp-metric-readers": { 

1414 "path": "gco_mcp/metric_readers/README.md", 

1415 "summary": "Pure helpers behind the read-only metric-reader tools — and how to add an aggregation mode, file format, error code, or whole new reader source.", 

1416 "topics": ["mcp", "metrics", "customization", "automation"], 

1417 "keywords": [ 

1418 "metric reader", 

1419 "cloudwatch", 

1420 "aggregation mode", 

1421 "file format", 

1422 "parquet", 

1423 "jsonl", 

1424 "error code", 

1425 "metrics_result", 

1426 "customize metrics", 

1427 "local root", 

1428 ], 

1429 "related": ["mcp-mission-judge", "mcp-mission", "MISSION", "mcp-server"], 

1430 }, 

1431 "mcp-mission-judge": { 

1432 "path": "gco_mcp/mission_judge/README.md", 

1433 "summary": "LLM-as-judge progress scoring internals — the versioned rubric, deterministic prompt, score parsing, and how to customize the scoring for your use case.", 

1434 "topics": ["mcp", "metrics", "customization", "automation"], 

1435 "keywords": [ 

1436 "semantic progress", 

1437 "judge", 

1438 "rubric", 

1439 "prompt", 

1440 "score parsing", 

1441 "progress_score", 

1442 "gco_enable_semantic_progress", 

1443 "llm as judge", 

1444 "customize rubric", 

1445 ], 

1446 "related": ["mcp-metric-readers", "mcp-mission", "MISSION", "mcp-server"], 

1447 }, 

1448} 

1449 

1450 

1451@mcp.resource("docs://gco/index") 

1452def docs_index() -> str: 

1453 """List all available GCO documentation, examples, and configuration resources.""" 

1454 sections = ["# GCO Resource Index\n"] 

1455 sections.append("## Project Overview") 

1456 sections.append("- `docs://gco/README` — Project README and overview") 

1457 sections.append("- `docs://gco/QUICKSTART` — Quick start guide (deploy in under 60 minutes)") 

1458 sections.append("- `docs://gco/TENETS` — Prioritized project tenets and north-star guidance") 

1459 sections.append("- `docs://gco/CONTRIBUTING` — Contributing guide\n") 

1460 

1461 sections.append("## Documentation") 

1462 sections.append( 

1463 "- `find_docs(query=..., topic=..., limit=...)` tool — search the docs catalog by topic and free-text query" 

1464 ) 

1465 sections.append( 

1466 "- `docs://gco/docs/by-topic/{topic}` — list every doc tagged with a given topic phrase" 

1467 ) 

1468 sections.append( 

1469 "- `docs://gco/docs/by-related/{doc_name}` — list every doc related to the given doc" 

1470 ) 

1471 for f in sorted(DOCS_DIR.glob("*.md")): 

1472 sections.append(f"- `docs://gco/docs/{f.stem}` — {f.stem}") 

1473 

1474 sections.append("\n## Architecture Decision Records") 

1475 sections.append( 

1476 "Append-only log of significant architectural decisions — the context, " 

1477 "the decision, and its consequences." 

1478 ) 

1479 sections.append("- `docs://gco/adr/index` — every ADR with its status (directory-driven)") 

1480 sections.append("- `docs://gco/adr/README` — when to write an ADR and the authoring process") 

1481 sections.append("- `docs://gco/adr/template` — the blank ADR template") 

1482 sections.append("- `docs://gco/adr/{id}` — read one ADR by four-digit id (e.g. `0001`)") 

1483 

1484 sections.append("\n## Package Internals") 

1485 sections.append( 

1486 "Developer-facing guides to the code packages under `gco_mcp/` — structure and " 

1487 "how to customize each. Also searchable via `find_docs`." 

1488 ) 

1489 for name, meta in PACKAGE_DOC_METADATA.items(): 

1490 sections.append(f"- `docs://gco/packages/{name}` — {meta.get('summary', '')}") 

1491 

1492 sections.append("\n## Example Manifests") 

1493 sections.append("- `docs://gco/examples/README` — Examples overview and usage guide") 

1494 sections.append( 

1495 "- `docs://gco/examples/guide` — How to create new job manifests (patterns & metadata)" 

1496 ) 

1497 

1498 sections.append("\n### Discovery") 

1499 sections.append( 

1500 "- `find_examples(query=..., category=..., gpu=..., opt_in=..., limit=...)` tool — " 

1501 "search the catalog by keyword and filters" 

1502 ) 

1503 sections.append( 

1504 "- `docs://gco/examples/by-category/{category}` — list every example in a given category" 

1505 ) 

1506 sections.append( 

1507 "- `docs://gco/examples/by-use-case/{use_case}` — list every example matching a use-case phrase" 

1508 ) 

1509 sections.append( 

1510 "- `docs://gco/examples/{name}` — full manifest plus metadata header for a single example\n" 

1511 ) 

1512 

1513 # Categorize examples 

1514 categories: dict[str, list[str]] = {} 

1515 for f in sorted(EXAMPLES_DIR.glob("*.yaml")): 

1516 name = f.stem 

1517 meta = EXAMPLE_METADATA.get(name, {}) 

1518 cat_value = meta.get("category", "Other") 

1519 cat = cat_value if isinstance(cat_value, str) else "Other" 

1520 summary_value = meta.get("summary", name) 

1521 summary = summary_value if isinstance(summary_value, str) else name 

1522 entry = f"- `docs://gco/examples/{name}` — {summary}" 

1523 categories.setdefault(cat, []).append(entry) 

1524 

1525 for cat, entries in categories.items(): 

1526 sections.append(f"### {cat}") 

1527 sections.extend(entries) 

1528 sections.append("") 

1529 

1530 sections.append("## Live State") 

1531 sections.append( 

1532 "- `gco://jobs/{region}/{job_name}` — live YAML for a Kubernetes Job in the " 

1533 "explicitly selected regional EKS cluster" 

1534 ) 

1535 sections.append( 

1536 "- `gco://inference/{endpoint_name}` — desired-state record for an inference endpoint " 

1537 "from the DynamoDB store" 

1538 ) 

1539 sections.append( 

1540 "- `gco://k8s/{region}/{namespace}/{kind}/{name}` — live YAML for any Kubernetes " 

1541 "resource from the explicitly selected regional EKS cluster" 

1542 ) 

1543 sections.append( 

1544 "- `gco://cluster/{region}/topology` — Karpenter NodePools plus Pending pods snapshot for one region" 

1545 ) 

1546 sections.append( 

1547 "- `costs://gco/summary/{days_window}` — cost summary for the given day window (positive integer)" 

1548 ) 

1549 sections.append("- `tasks://gco/{task_id}` — current status of a FastMCP background task by ID") 

1550 sections.append( 

1551 "- `mission://sessions/{session_id}` — Mission session state, report, or audit replay " 

1552 "when `GCO_ENABLE_MISSION=true`" 

1553 ) 

1554 sections.append("") 

1555 

1556 sections.append("## Other Resource Groups") 

1557 sections.append("- `k8s://gco/manifests/index` — Kubernetes manifests deployed to EKS") 

1558 sections.append("- `iam://gco/policies/index` — IAM policy templates") 

1559 sections.append("- `infra://gco/index` — Dockerfiles, Helm charts, CI/CD config") 

1560 sections.append("- `ci://gco/index` — GitHub Actions workflows, composite actions, templates") 

1561 sections.append( 

1562 "- `images://gco/index` — ECR repositories, tags, images, and replication status" 

1563 ) 

1564 sections.append("- `source://gco/index` — Source code browser") 

1565 sections.append("- `demos://gco/index` — Demo walkthroughs and scripts") 

1566 sections.append("- `clients://gco/index` — API client examples (Python, curl, AWS CLI)") 

1567 sections.append("- `scripts://gco/index` — Utility scripts") 

1568 sections.append("- `tests://gco/index` — Test suite documentation and patterns") 

1569 sections.append( 

1570 "- `config://gco/index` — authoritative CDK configuration, MCP feature flags, and environment variables" 

1571 ) 

1572 sections.append("- `mcp://gco/tools/index` — live registered-tool catalog") 

1573 sections.append("- `mcp://gco/resources/index` — live static-resource and template catalog") 

1574 sections.append("- `mcp://gco/feature-flags` — authoritative feature-gate mapping") 

1575 return "\n".join(sections) 

1576 

1577 

1578@mcp.resource("docs://gco/README") 

1579def readme_resource() -> str: 

1580 """The main project README with overview and quickstart information.""" 

1581 return (PROJECT_ROOT / "README.md").read_text() 

1582 

1583 

1584@mcp.resource("docs://gco/QUICKSTART") 

1585def quickstart_resource() -> str: 

1586 """Quick start guide — get running in under 60 minutes.""" 

1587 path = PROJECT_ROOT / "QUICKSTART.md" 

1588 if not path.is_file(): 

1589 return "QUICKSTART.md not found." 

1590 return path.read_text() 

1591 

1592 

1593@mcp.resource("docs://gco/TENETS") 

1594def tenets_resource() -> str: 

1595 """Prioritized project tenets and north-star decision guidance.""" 

1596 meta = ROOT_DOC_METADATA["TENETS"] 

1597 rel_path = str(meta["path"]) 

1598 path = PROJECT_ROOT / rel_path 

1599 if not path.is_file(): 

1600 return f"{rel_path} not found." 

1601 content = path.read_text() 

1602 topics = meta.get("topics", []) 

1603 related = meta.get("related", []) 

1604 header_lines = [] 

1605 if isinstance(topics, list) and topics: 

1606 header_lines.append(f"<!-- Topics: {', '.join(str(t) for t in topics)} -->") 

1607 if isinstance(related, list) and related: 

1608 header_lines.append(f"<!-- Related: {', '.join(str(r) for r in related)} -->") 

1609 return "\n".join(header_lines) + "\n\n" + content 

1610 

1611 

1612@mcp.resource("docs://gco/CONTRIBUTING") 

1613def contributing_resource() -> str: 

1614 """Contributing guide — how to contribute to the project.""" 

1615 path = PROJECT_ROOT / "CONTRIBUTING.md" 

1616 if not path.is_file(): 

1617 return "CONTRIBUTING.md not found." 

1618 return path.read_text() 

1619 

1620 

1621@mcp.resource("docs://gco/docs/{doc_name}") 

1622def doc_resource(doc_name: str) -> str: 

1623 """Read a documentation file by name (e.g. ARCHITECTURE, CLI, INFERENCE). 

1624 

1625 Prepends an HTML-comment header with ``Topics:`` and ``Related:`` lines 

1626 pulled from ``DOC_METADATA`` so an LLM consuming the rendered markdown 

1627 sees the doc's classification without it bleeding into the rendered 

1628 output. HTML comments are used rather than ``#`` because docs are 

1629 markdown — Python-style comments would render as text. 

1630 """ 

1631 path = DOCS_DIR / f"{doc_name}.md" 

1632 if not path.is_file(): 

1633 available = [f.stem for f in DOCS_DIR.glob("*.md")] 

1634 return f"Document '{doc_name}' not found. Available: {', '.join(available)}" 

1635 content = path.read_text() 

1636 meta = DOC_METADATA.get(doc_name, {}) 

1637 header_lines = [] 

1638 topics = meta.get("topics", []) 

1639 if isinstance(topics, list) and topics: 

1640 header_lines.append(f"<!-- Topics: {', '.join(str(t) for t in topics)} -->") 

1641 related = meta.get("related", []) 

1642 if isinstance(related, list) and related: 

1643 header_lines.append(f"<!-- Related: {', '.join(str(r) for r in related)} -->") 

1644 if header_lines: 

1645 return "\n".join(header_lines) + "\n\n" + content 

1646 return content 

1647 

1648 

1649@mcp.resource("docs://gco/packages/{package_name}") 

1650def package_doc_resource(package_name: str) -> str: 

1651 """Read a package-level README by slug (e.g. mcp-mission, mcp-metric-readers). 

1652 

1653 Serves the developer-facing internals guides catalogued in 

1654 ``PACKAGE_DOC_METADATA`` — the README files that live next to the code 

1655 under ``gco_mcp/`` rather than in ``docs/``. Prepends an HTML-comment header 

1656 with ``Topics:`` and ``Related:`` lines (mirroring :func:`doc_resource`) 

1657 so a consuming LLM sees the classification without it bleeding into the 

1658 rendered markdown. An unknown slug returns the literal ``Package doc 'X' 

1659 not found. Available: ...`` string so callers can recover. 

1660 """ 

1661 meta = PACKAGE_DOC_METADATA.get(package_name) 

1662 if meta is None: 

1663 available = ", ".join(sorted(PACKAGE_DOC_METADATA.keys())) 

1664 return f"Package doc '{package_name}' not found. Available: {available}" 

1665 rel_path = str(meta.get("path", "")) 

1666 path = PROJECT_ROOT / rel_path 

1667 if not path.is_file(): 

1668 return f"Package doc '{package_name}' file not found at '{rel_path}'." 

1669 content = path.read_text() 

1670 header_lines = [] 

1671 topics = meta.get("topics", []) 

1672 if isinstance(topics, list) and topics: 

1673 header_lines.append(f"<!-- Topics: {', '.join(str(t) for t in topics)} -->") 

1674 related = meta.get("related", []) 

1675 if isinstance(related, list) and related: 

1676 header_lines.append(f"<!-- Related: {', '.join(str(r) for r in related)} -->") 

1677 if header_lines: 

1678 return "\n".join(header_lines) + "\n\n" + content 

1679 return content 

1680 

1681 

1682@mcp.resource("docs://gco/examples/README") 

1683def examples_readme_resource() -> str: 

1684 """Examples README — overview of all example manifests with usage instructions.""" 

1685 path = EXAMPLES_DIR / "README.md" 

1686 if not path.is_file(): 

1687 return "Examples README.md not found." 

1688 return path.read_text() 

1689 

1690 

1691@mcp.resource("docs://gco/examples/guide") 

1692def examples_guide_resource() -> str: 

1693 """How to create new job manifests — patterns, metadata, and best practices. 

1694 

1695 Use this resource when you need to write a new Kubernetes manifest for GCO. 

1696 It provides the metadata for every existing example so you can pick the 

1697 closest one as a starting point and adapt it. 

1698 """ 

1699 lines = ["# GCO Example Manifest Guide\n"] 

1700 lines.append("Use this guide to create new Kubernetes manifests for GCO. Pick the closest") 

1701 lines.append("existing example as a starting point, then adapt it.\n") 

1702 lines.append("## All Examples with Metadata\n") 

1703 lines.append("| Example | Category | Keywords | GPU | Opt-in | How to Submit |") 

1704 lines.append("|---------|----------|----------|-----|--------|---------------|") 

1705 for name, meta in EXAMPLE_METADATA.items(): 

1706 gpu = meta.get("gpu", "no") 

1707 opt_in = meta.get("opt_in", "—") or "—" 

1708 submission = meta.get("submission", "") 

1709 keywords = meta.get("keywords", []) 

1710 keywords_cell = ", ".join(keywords) if isinstance(keywords, list) and keywords else "—" 

1711 lines.append( 

1712 f"| `{name}` | {meta['category']} | {keywords_cell} | {gpu} | {opt_in} | " 

1713 f"`{submission}` |" 

1714 ) 

1715 

1716 lines.append("\n## Common Patterns\n") 

1717 lines.append("### Namespace") 

1718 lines.append( 

1719 "All GCO jobs use `namespace: gco-jobs`. Inference uses `namespace: gco-inference`.\n" 

1720 ) 

1721 lines.append("### Security Context (required)") 

1722 lines.append("```yaml") 

1723 lines.append("securityContext:") 

1724 lines.append(" runAsNonRoot: true") 

1725 lines.append(" runAsUser: 1000") 

1726 lines.append(" runAsGroup: 1000") 

1727 lines.append("containers:") 

1728 lines.append("- securityContext:") 

1729 lines.append(" allowPrivilegeEscalation: false") 

1730 lines.append(" capabilities:") 

1731 lines.append(' drop: ["ALL"]') 

1732 lines.append("```\n") 

1733 lines.append("### GPU Resources") 

1734 lines.append("```yaml") 

1735 lines.append("resources:") 

1736 lines.append(" requests:") 

1737 lines.append(' nvidia.com/gpu: "1"') 

1738 lines.append(" limits:") 

1739 lines.append(' nvidia.com/gpu: "1"') 

1740 lines.append("tolerations:") 

1741 lines.append("- key: nvidia.com/gpu") 

1742 lines.append(" operator: Equal") 

1743 lines.append(' value: "true"') 

1744 lines.append(" effect: NoSchedule") 

1745 lines.append("```\n") 

1746 lines.append("### EFS Shared Storage") 

1747 lines.append("```yaml") 

1748 lines.append("volumeMounts:") 

1749 lines.append("- name: shared-storage") 

1750 lines.append(" mountPath: /mnt/gco") 

1751 lines.append("volumes:") 

1752 lines.append("- name: shared-storage") 

1753 lines.append(" persistentVolumeClaim:") 

1754 lines.append(" claimName: gco-shared-storage") 

1755 lines.append("```\n") 

1756 lines.append("### Prevent Node Consolidation (long-running jobs)") 

1757 lines.append("```yaml") 

1758 lines.append("metadata:") 

1759 lines.append(" annotations:") 

1760 lines.append(' karpenter.sh/do-not-disrupt: "true"') 

1761 lines.append("```\n") 

1762 lines.append("### Submission Methods") 

1763 lines.append("1. **SQS (recommended):** `gco jobs submit-sqs <manifest> --region <region>`") 

1764 lines.append("2. **API Gateway:** `gco jobs submit <manifest>`") 

1765 lines.append("3. **Direct kubectl:** `gco jobs submit-direct <manifest> -r <region>`") 

1766 lines.append("4. **kubectl apply:** `kubectl apply -f <manifest>`") 

1767 return "\n".join(lines) 

1768 

1769 

1770@mcp.resource("docs://gco/examples/{example_name}") 

1771def example_resource(example_name: str) -> str: 

1772 """Read an example manifest by name, with metadata context for creating similar jobs. 

1773 

1774 Returns the raw YAML manifest preceded by a metadata header that describes 

1775 what the example does, its requirements, and how to submit it. 

1776 """ 

1777 path = EXAMPLES_DIR / f"{example_name}.yaml" 

1778 if not path.is_file(): 

1779 available = [f.stem for f in EXAMPLES_DIR.glob("*.yaml")] 

1780 return f"Example '{example_name}' not found. Available: {', '.join(available)}" 

1781 

1782 meta = EXAMPLE_METADATA.get(example_name, {}) 

1783 header_lines = [] 

1784 if meta: 

1785 header_lines.append(f"# Example: {example_name}") 

1786 header_lines.append(f"# Category: {meta.get('category', 'Unknown')}") 

1787 header_lines.append(f"# Summary: {meta.get('summary', '')}") 

1788 if meta.get("gpu", "no") != "no": 

1789 header_lines.append(f"# GPU/Accelerator: {meta['gpu']}") 

1790 if meta.get("opt_in"): 

1791 header_lines.append(f"# Opt-in required: {meta['opt_in']}") 

1792 header_lines.append( 

1793 f"# Submit with: {meta.get('submission', 'kubectl apply -f examples/' + example_name + '.yaml')}" 

1794 ) 

1795 keywords = meta.get("keywords", []) 

1796 if isinstance(keywords, list) and keywords: 

1797 header_lines.append(f"# Keywords: {', '.join(keywords)}") 

1798 instance_types = meta.get("instance_types", []) 

1799 if isinstance(instance_types, list) and instance_types: 

1800 header_lines.append(f"# Instance Types: {', '.join(instance_types)}") 

1801 use_cases = meta.get("use_cases", []) 

1802 if isinstance(use_cases, list) and use_cases: 

1803 header_lines.append(f"# Use Cases: {', '.join(use_cases)}") 

1804 related = meta.get("related", []) 

1805 if isinstance(related, list) and related: 

1806 header_lines.append(f"# Related: {', '.join(related)}") 

1807 header_lines.append("#") 

1808 header_lines.append("# --- Manifest begins below ---\n") 

1809 

1810 manifest = path.read_text() 

1811 if header_lines: 

1812 return "\n".join(header_lines) + manifest 

1813 return manifest 

1814 

1815 

1816@mcp.resource("docs://gco/examples/by-category/{category}") 

1817def examples_by_category_resource(category: str) -> str: 

1818 """List examples grouped by category. 

1819 

1820 Returns a markdown listing of every example in the given category. Match 

1821 is case-insensitive against the entry's ``category`` field. When the 

1822 category is not recognised, returns the literal "Category 'X' not found. 

1823 Available: ..." string so callers can recover. 

1824 """ 

1825 matches = [ 

1826 (name, meta) 

1827 for name, meta in EXAMPLE_METADATA.items() 

1828 if str(meta.get("category", "")).lower() == category.lower() 

1829 ] 

1830 if not matches: 

1831 available = sorted({str(m.get("category", "")) for m in EXAMPLE_METADATA.values()}) 

1832 return f"Category '{category}' not found. Available: {', '.join(available)}" 

1833 lines = [f"# Examples in category: {category}\n"] 

1834 for name, meta in sorted(matches): 

1835 lines.append(f"- `docs://gco/examples/{name}` — {meta.get('summary', '')}") 

1836 return "\n".join(lines) 

1837 

1838 

1839@mcp.resource("docs://gco/examples/by-use-case/{use_case}") 

1840def examples_by_use_case_resource(use_case: str) -> str: 

1841 """List examples whose use_cases include the given phrase (case-insensitive). 

1842 

1843 Substring match against every entry in each example's ``use_cases`` list. 

1844 When nothing matches, returns the literal "No examples match use case 

1845 'X'." string with a pointer to ``find_examples`` for broader search. 

1846 """ 

1847 needle = use_case.lower() 

1848 matches: list[tuple[str, dict[str, str | list[str]]]] = [] 

1849 for name, meta in EXAMPLE_METADATA.items(): 

1850 ucs = meta.get("use_cases", []) 

1851 if isinstance(ucs, list) and any(needle in str(uc).lower() for uc in ucs): 

1852 matches.append((name, meta)) 

1853 if not matches: 

1854 return ( 

1855 f"No examples match use case '{use_case}'. " 

1856 "Try `find_examples(query=...)` for broader search." 

1857 ) 

1858 lines = [f"# Examples matching use case: {use_case}\n"] 

1859 for name, meta in sorted(matches): 

1860 lines.append(f"- `docs://gco/examples/{name}` — {meta.get('summary', '')}") 

1861 return "\n".join(lines) 

1862 

1863 

1864@mcp.resource("docs://gco/docs/by-topic/{topic}") 

1865def docs_by_topic_resource(topic: str) -> str: 

1866 """List docs whose topics include the given phrase (case-insensitive). 

1867 

1868 Substring match against every entry in each doc's ``topics`` list. When 

1869 nothing matches, returns the literal ``Topic 'X' not found. Available: 

1870 ...`` string with the union of every known topic so callers can recover. 

1871 """ 

1872 needle = topic.lower() 

1873 matches: list[tuple[str, dict[str, str | list[str]]]] = [] 

1874 for name, meta in DOC_METADATA.items(): 

1875 topics = meta.get("topics", []) 

1876 if isinstance(topics, list) and any(needle in str(t).lower() for t in topics): 

1877 matches.append((name, meta)) 

1878 if not matches: 

1879 available = sorted( 

1880 { 

1881 str(t) 

1882 for meta in DOC_METADATA.values() 

1883 for t in (meta.get("topics", []) if isinstance(meta.get("topics"), list) else []) 

1884 } 

1885 ) 

1886 return f"Topic '{topic}' not found. Available: {', '.join(available)}" 

1887 lines = [f"# Docs matching topic: {topic}\n"] 

1888 for name, meta in sorted(matches): 

1889 lines.append(f"- `docs://gco/docs/{name}` — {meta.get('summary', '')}") 

1890 return "\n".join(lines) 

1891 

1892 

1893@mcp.resource("docs://gco/docs/by-related/{doc_name}") 

1894def docs_by_related_resource(doc_name: str) -> str: 

1895 """List docs related to ``doc_name``. 

1896 

1897 Combines two views of the bidirectional relation: every doc that lists 

1898 ``doc_name`` in its own ``related`` field (referenced by) and every doc 

1899 ``doc_name`` itself lists (references). Unknown names return the literal 

1900 ``Doc 'X' not found. Available: ...`` string. 

1901 """ 

1902 if doc_name not in DOC_METADATA: 

1903 available = sorted(DOC_METADATA.keys()) 

1904 return f"Doc '{doc_name}' not found. Available: {', '.join(available)}" 

1905 

1906 referenced_by: list[str] = [] 

1907 for name, meta in DOC_METADATA.items(): 

1908 related = meta.get("related", []) 

1909 if isinstance(related, list) and doc_name in related: 

1910 referenced_by.append(name) 

1911 

1912 references: list[str] = [] 

1913 referenced_self = DOC_METADATA[doc_name].get("related", []) 

1914 if isinstance(referenced_self, list): 

1915 references = [str(r) for r in referenced_self] 

1916 

1917 lines = [f"# Docs related to {doc_name}\n"] 

1918 if references: 

1919 lines.append("## Referenced by this doc") 

1920 for ref in sorted(set(references)): 

1921 meta = DOC_METADATA.get(ref, {}) 

1922 lines.append(f"- `docs://gco/docs/{ref}` — {meta.get('summary', '')}") 

1923 lines.append("") 

1924 if referenced_by: 

1925 lines.append("## Docs that reference this one") 

1926 for ref in sorted(set(referenced_by)): 

1927 meta = DOC_METADATA.get(ref, {}) 

1928 lines.append(f"- `docs://gco/docs/{ref}` — {meta.get('summary', '')}") 

1929 return "\n".join(lines) 

1930 

1931 

1932# --------------------------------------------------------------------------- 

1933# Architecture Decision Records (ADRs) — docs://gco/adr/* 

1934# 

1935# The ADR catalog under ``docs/adr/`` is directory-driven: both the index and 

1936# the per-record resource derive everything from the files on disk, so 

1937# recording a new decision needs no change here. ``NNNN-title.md`` files are the 

1938# records; ``README.md`` (process guide) and ``template.md`` (blank form) are 

1939# guides, not records, and are excluded from the record listing. 

1940# --------------------------------------------------------------------------- 

1941 

1942_ADR_ID_RE = re.compile(r"^\d{4}-") 

1943_ADR_TITLE_PREFIX_RE = re.compile(r"^\d+\.\s*") 

1944 

1945 

1946def _adr_record_files() -> list[Path]: 

1947 """Return the numbered ADR record files (``NNNN-*.md``), sorted by id.""" 

1948 if not ADR_DIR.is_dir(): 

1949 return [] 

1950 return sorted(p for p in ADR_DIR.glob("*.md") if _ADR_ID_RE.match(p.name)) 

1951 

1952 

1953def _parse_adr(path: Path) -> dict[str, str]: 

1954 """Extract ``id``, ``title``, and ``status`` from an ADR markdown file. 

1955 

1956 Title is the first level-1 heading with any ``NNNN.`` numeric prefix 

1957 stripped; status is read from the ``- **Status:** ...`` metadata line. Both 

1958 fall back to sensible defaults so a malformed file still lists rather than 

1959 breaking the index. 

1960 """ 

1961 title = "" 

1962 status = "" 

1963 for raw in path.read_text(encoding="utf-8").splitlines(): 

1964 line = raw.strip() 

1965 if not title and line.startswith("# "): 

1966 title = _ADR_TITLE_PREFIX_RE.sub("", line[2:].strip()) 

1967 continue 

1968 if not status: 

1969 # Normalize "- **Status:** Accepted" to "status: accepted" so the 

1970 # label is matched regardless of list marker or emphasis. 

1971 plain = line.lstrip("-* ").replace("*", "") 

1972 if plain.lower().startswith("status"): 

1973 status = plain[len("status") :].lstrip(": ").strip().rstrip(".") 

1974 return { 

1975 "id": path.stem, 

1976 "title": title or path.stem, 

1977 "status": status or "Unknown", 

1978 } 

1979 

1980 

1981def _resolve_adr(adr_id: str) -> Path | None: 

1982 """Resolve an ADR request to a file under ``docs/adr/``, or ``None``. 

1983 

1984 Accepts a full filename stem (``0001-record-architecture-decisions``, 

1985 ``README``, ``template``) or a numeric id in any zero-padding (``1`` -> 

1986 ``0001``). Rejects anything containing a path separator or ``..`` so a 

1987 crafted id cannot escape the directory; because the sanitized candidate has 

1988 no separators, the joined path is always a direct child of ``docs/adr/``. 

1989 """ 

1990 candidate = adr_id.strip() 

1991 if not candidate or "/" in candidate or "\\" in candidate or ".." in candidate: 

1992 return None 

1993 if candidate.isdigit(): 

1994 want = candidate.zfill(4) 

1995 return next((p for p in _adr_record_files() if p.name[:4] == want), None) 

1996 path = ADR_DIR / f"{candidate}.md" 

1997 return path if path.is_file() else None 

1998 

1999 

2000@mcp.resource("docs://gco/adr/index") 

2001def adr_index_resource() -> str: 

2002 """List every Architecture Decision Record with its id, title, and status. 

2003 

2004 Directory-driven: scans ``docs/adr/`` for numbered ``NNNN-title.md`` records 

2005 at read time, so a newly added ADR appears here with no code change. The 

2006 process guide and the blank template are available at 

2007 ``docs://gco/adr/README`` and ``docs://gco/adr/template``. 

2008 """ 

2009 lines = ["# Architecture Decision Records\n"] 

2010 lines.append( 

2011 "Append-only log of significant architectural decisions (context, " 

2012 "decision, consequences). Read the process at `docs://gco/adr/README` " 

2013 "and start a new record from `docs://gco/adr/template`.\n" 

2014 ) 

2015 files = _adr_record_files() 

2016 if not files: 

2017 lines.append("_No ADRs have been recorded yet._") 

2018 return "\n".join(lines) 

2019 for path in files: 

2020 meta = _parse_adr(path) 

2021 lines.append(f"- `docs://gco/adr/{path.name[:4]}` — {meta['title']} ({meta['status']})") 

2022 return "\n".join(lines) 

2023 

2024 

2025@mcp.resource("docs://gco/adr/{adr_id}") 

2026def adr_resource(adr_id: str) -> str: 

2027 """Read a single ADR by id, filename stem, or guide name. 

2028 

2029 Accepts a four-digit id (``0001``), a full stem 

2030 (``0001-record-architecture-decisions``), or the ``README`` / ``template`` 

2031 guides. An unknown id returns the literal ``ADR 'X' not found. Available: 

2032 ...`` string listing the numeric ids so callers can recover. 

2033 """ 

2034 path = _resolve_adr(adr_id) 

2035 if path is None: 

2036 available = ", ".join(p.name[:4] for p in _adr_record_files()) or "none" 

2037 return f"ADR '{adr_id}' not found. Available: {available}" 

2038 return path.read_text(encoding="utf-8")