cloud-finops-mcp 1.21.0__tar.gz

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.
Files changed (59) hide show
  1. cloud_finops_mcp-1.21.0/.gitignore +53 -0
  2. cloud_finops_mcp-1.21.0/PKG-INFO +218 -0
  3. cloud_finops_mcp-1.21.0/README.md +187 -0
  4. cloud_finops_mcp-1.21.0/pyproject.toml +86 -0
  5. cloud_finops_mcp-1.21.0/scripts/sync_references.py +92 -0
  6. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/__init__.py +14 -0
  7. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/__main__.py +16 -0
  8. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/.gitignore +3 -0
  9. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-ai-dev-tools.md +445 -0
  10. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-ai-self-hosted-vs-managed.md +300 -0
  11. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-ai-value-management.md +324 -0
  12. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-allocation-showback.md +391 -0
  13. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-anomaly-management.md +325 -0
  14. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-anthropic.md +288 -0
  15. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-aws.md +2657 -0
  16. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-azure-openai.md +418 -0
  17. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-azure.md +2997 -0
  18. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-bedrock.md +361 -0
  19. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-chargeback.md +394 -0
  20. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-databricks.md +454 -0
  21. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-fabric.md +320 -0
  22. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-for-ai.md +442 -0
  23. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-framework.md +398 -0
  24. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-gcp.md +550 -0
  25. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-genai-capacity.md +237 -0
  26. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-itam.md +339 -0
  27. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-kubernetes.md +438 -0
  28. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-oci.md +180 -0
  29. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-onboarding-workloads.md +418 -0
  30. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-sam.md +301 -0
  31. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-snowflake.md +316 -0
  32. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-tagging.md +259 -0
  33. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-vertexai.md +295 -0
  34. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/finops-waste-detection-playbooks.md +655 -0
  35. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/greenops-cloud-carbon.md +650 -0
  36. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/optimnow-methodology.md +163 -0
  37. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/aws-cross-az-egress.md +92 -0
  38. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/aws-idle-load-balancer.md +86 -0
  39. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/aws-orphaned-ebs-volumes.md +92 -0
  40. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/aws-oversized-rds.md +92 -0
  41. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/aws-snapshot-sprawl.md +86 -0
  42. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/aws-zombie-nat-gateway.md +91 -0
  43. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/azure-app-service-overprovisioned.md +107 -0
  44. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/azure-idle-sql-database.md +84 -0
  45. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/azure-log-analytics-sprawl.md +87 -0
  46. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/azure-orphan-disks.md +90 -0
  47. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/cross-cloud-schedule-blindness.md +115 -0
  48. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/cross-cloud-untagged-spend-drift.md +132 -0
  49. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/gcp-cloud-functions-cold-starts.md +108 -0
  50. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/gcp-idle-gke-autopilot.md +90 -0
  51. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/data/playbooks/gcp-orphan-persistent-disks.md +86 -0
  52. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/metadata.py +246 -0
  53. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/server.py +177 -0
  54. cloud_finops_mcp-1.21.0/src/cloud_finops_mcp/tools.py +238 -0
  55. cloud_finops_mcp-1.21.0/tests/__init__.py +0 -0
  56. cloud_finops_mcp-1.21.0/tests/conftest.py +42 -0
  57. cloud_finops_mcp-1.21.0/tests/test_e2e.py +133 -0
  58. cloud_finops_mcp-1.21.0/tests/test_metadata.py +78 -0
  59. cloud_finops_mcp-1.21.0/tests/test_tools.py +191 -0
@@ -0,0 +1,53 @@
1
+ # Internal
2
+ INTERNAL_NOTES.md
3
+
4
+ # Environment
5
+ .env
6
+ .env.*
7
+
8
+ # OS files
9
+ .DS_Store
10
+ Thumbs.db
11
+ NUL
12
+
13
+ # Claude Code local settings (any depth - root, cloud-finops/, etc.)
14
+ .claude/settings.local.json
15
+ **/.claude/settings.local.json
16
+
17
+ # Claude Code local hooks config
18
+ claude-hooks-settings.json
19
+
20
+ # Claude Code worktrees (embedded git repos)
21
+ .claude/worktrees/
22
+
23
+ # Local-only nested .claude/ directories (e.g. cloud-finops/.claude/)
24
+ cloud-finops/.claude/
25
+
26
+ # Local working notes / plan drafts
27
+ plan-*.md
28
+ plan-remediation-*.md
29
+
30
+ # Pipeline (private until public release)
31
+ pipeline/
32
+
33
+ # Reference file backups
34
+ cloud-finops/references/.backups/
35
+
36
+ # Distribution archive
37
+ cloud-finops.zip
38
+
39
+ # Python build artefacts (mcp_server/)
40
+ __pycache__/
41
+ *.py[cod]
42
+ *.egg-info/
43
+ .pytest_cache/
44
+ .ruff_cache/
45
+ mcp_server/build/
46
+ mcp_server/dist/
47
+ mcp_server/.venv/
48
+
49
+ # LinkedIn post drafts
50
+ linkedin-post-*.md
51
+
52
+ # Review adjudication
53
+ review-adjudication.md
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloud-finops-mcp
3
+ Version: 1.21.0
4
+ Summary: MCP server exposing the OptimNow Cloud FinOps skill (28 references) as queryable tools.
5
+ Project-URL: Homepage, https://github.com/OptimNow/cloud-finops-skills
6
+ Project-URL: Repository, https://github.com/OptimNow/cloud-finops-skills
7
+ Project-URL: Issues, https://github.com/OptimNow/cloud-finops-skills/issues
8
+ Project-URL: Documentation, https://github.com/OptimNow/cloud-finops-skills/tree/main/mcp_server
9
+ Author-email: OptimNow <contact@optimnow.io>
10
+ Maintainer-email: Jean Latière <j.latiere@gmail.com>
11
+ License: CC-BY-SA-4.0
12
+ Keywords: aws,azure,claude,cloud,cost,finops,gcp,mcp
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Information Technology
16
+ Classifier: License :: OSI Approved
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: mcp>=1.0.0
25
+ Requires-Dist: pyyaml>=6.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
28
+ Requires-Dist: pytest>=7.4; extra == 'dev'
29
+ Requires-Dist: ruff>=0.5; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # cloud-finops-mcp
33
+
34
+ MCP server exposing the [OptimNow Cloud FinOps skill](https://github.com/OptimNow/cloud-finops-skills)
35
+ (28 reference files + 15 named-pattern playbooks) as queryable tools for any
36
+ MCP-aware client (Claude Code, Cursor, Codex CLI, Windsurf, Aider, Cline, etc.).
37
+
38
+ The skill itself ships in canonical Claude Agent-Skills format and is also installable
39
+ via the cross-tool installer (`./install.sh`) for direct context injection. This MCP
40
+ server is the **enrichment path**: instead of loading the full skill into the
41
+ prompt, the agent calls tools to discover, filter, and fetch only what it needs.
42
+
43
+ ## What the server exposes
44
+
45
+ Six tools, all read-only, split across two surfaces.
46
+
47
+ **References** — long-form provider and discipline files (~300-500 lines each):
48
+
49
+ | Tool | Purpose |
50
+ |---|---|
51
+ | `list_references()` | List all 28 references with their FCP metadata. |
52
+ | `get_reference(name)` | Fetch the full markdown body of one reference. |
53
+ | `find_references(domain?, capability?, phase?, persona?, maturity?)` | Faceted query over the FinOps Capability/Phase frontmatter. |
54
+
55
+ The reference faceted query supports any combination of:
56
+
57
+ - `domain` - FinOps Framework domain (e.g. `Optimize Usage & Cost`, `Quantify Business Value`)
58
+ - `capability` - FinOps capability (matches both primary and secondary)
59
+ - `phase` - `Inform`, `Optimize`, `Operate`
60
+ - `persona` - matches both primary and collaborating personas
61
+ - `maturity` - `Crawl`, `Walk`, `Run`
62
+
63
+ **Playbooks** — small named-pattern runbooks (~80-130 lines each):
64
+
65
+ | Tool | Purpose |
66
+ |---|---|
67
+ | `list_playbooks()` | List all 15 named-pattern playbooks with their metadata. |
68
+ | `get_playbook(name)` | Fetch the full markdown body of one playbook. |
69
+ | `find_playbooks(scope?, service?, waste_category?, confidence?)` | Faceted query over the playbook frontmatter. |
70
+
71
+ The playbook faceted query supports:
72
+
73
+ - `scope` - `aws`, `azure`, `gcp`, or `cross-cloud`
74
+ - `service` - provider service (e.g. `AWS NAT Gateway`); exact-match
75
+ - `waste_category` - `orphaned`, `idle`, `overprovisioned`, `commitment-mismatch`,
76
+ `schedule-blindness`, `modernization`, `ai-ml-inefficiency`, `egress`
77
+ - `confidence` - `obvious`, `likely`, `possible` (OptimNow three-tier model)
78
+
79
+ All filters across both surfaces AND together. String matches are case-insensitive
80
+ and exact (no substring matching).
81
+
82
+ **When to use which surface:**
83
+
84
+ - A **playbook** answers *"how do I detect/fix this specific pattern?"* (zombie NAT,
85
+ snapshot sprawl, idle ELB). It includes problem statement, symptoms, a detection
86
+ query (CUR / KQL / BigQuery SQL / CLI), fix steps, and the anti-pattern.
87
+ - A **reference** answers anything broader: billing mechanics, commitment strategy,
88
+ allocation methodology, persona-specific framings, or cross-pattern reasoning.
89
+
90
+ ## Install
91
+
92
+ ```bash
93
+ pip install cloud-finops-mcp
94
+ ```
95
+
96
+ Or run without installing via [`uv`](https://docs.astral.sh/uv/):
97
+
98
+ ```bash
99
+ uvx cloud-finops-mcp
100
+ ```
101
+
102
+ ## Configure your MCP client
103
+
104
+ After install, point your client at the `cloud-finops-mcp` console script.
105
+
106
+ ### Claude Code
107
+
108
+ Project-level (`.mcp.json` at the repo root) or user-level (`~/.claude/mcp.json`):
109
+
110
+ ```json
111
+ {
112
+ "mcpServers": {
113
+ "cloud-finops": {
114
+ "command": "cloud-finops-mcp"
115
+ }
116
+ }
117
+ }
118
+ ```
119
+
120
+ Restart Claude Code, then run `/mcp` to confirm the server is connected.
121
+
122
+ ### Cursor
123
+
124
+ `~/.cursor/mcp.json`:
125
+
126
+ ```json
127
+ {
128
+ "mcpServers": {
129
+ "cloud-finops": {
130
+ "command": "cloud-finops-mcp"
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### Codex CLI
137
+
138
+ `~/.codex/config.toml`:
139
+
140
+ ```toml
141
+ [mcp_servers.cloud-finops]
142
+ command = "cloud-finops-mcp"
143
+ ```
144
+
145
+ ### Windsurf
146
+
147
+ `~/.windsurf/mcp.json`:
148
+
149
+ ```json
150
+ {
151
+ "mcpServers": {
152
+ "cloud-finops": {
153
+ "command": "cloud-finops-mcp"
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ ### Any other MCP client
160
+
161
+ The server speaks MCP over stdio. Point any compatible client at `cloud-finops-mcp`
162
+ (or `python -m cloud_finops_mcp`).
163
+
164
+ ## Example tool calls
165
+
166
+ Agent prompt: *"Use the cloud-finops MCP to find references for the Optimize phase
167
+ aimed at Engineering."*
168
+
169
+ Calls `find_references(phase="Optimize", persona="Engineering")` and gets back the
170
+ filtered subset (AWS, Azure, GCP, Bedrock, Databricks, etc.) without loading the full
171
+ skill into the prompt.
172
+
173
+ Agent prompt: *"Pull the AWS reference."*
174
+
175
+ Calls `get_reference(name="finops-aws")` and gets back the full markdown body
176
+ (~300 lines) instead of the entire 28-file knowledge base.
177
+
178
+ Agent prompt: *"Show me the obvious-confidence AWS waste playbooks."*
179
+
180
+ Calls `find_playbooks(scope="aws", confidence="obvious")` and gets back the list
181
+ of high-signal AWS patterns (zombie NAT gateway, orphaned EBS volumes, etc.).
182
+
183
+ Agent prompt: *"Walk me through the zombie NAT gateway pattern."*
184
+
185
+ Calls `get_playbook(name="aws-zombie-nat-gateway")` and gets back the ~90-line
186
+ runbook (problem, symptoms, detection query, fix, anti-pattern, see-also).
187
+
188
+ ## When to use this vs the installer
189
+
190
+ | If you... | Use |
191
+ |---|---|
192
+ | Want the skill loaded as static context for every chat | The cross-tool installer (`./install.sh`) |
193
+ | Have a big-codebase session with limited context budget | The MCP server (fetch on demand) |
194
+ | Want to filter references by FinOps domain/capability/phase/persona/maturity | The MCP server (`find_references`) |
195
+ | Use a client that doesn't support MCP | The cross-tool installer |
196
+
197
+ The two paths are complementary. You can install both.
198
+
199
+ ## Development
200
+
201
+ ```bash
202
+ git clone https://github.com/OptimNow/cloud-finops-skills.git
203
+ cd cloud-finops-skills/mcp_server
204
+ python scripts/sync_references.py # populate src/cloud_finops_mcp/data/
205
+ pip install -e ".[dev]"
206
+ pytest
207
+ ```
208
+
209
+ ## Versioning
210
+
211
+ The PyPI package version tracks the skill release tag. Tagging `v1.13` on the
212
+ parent repo triggers both the skill release zip and a new `cloud-finops-mcp` PyPI
213
+ publish so the bundled references match what the rest of the repo ships.
214
+
215
+ ## License
216
+
217
+ [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) - same as the parent
218
+ skill. Credit OptimNow.
@@ -0,0 +1,187 @@
1
+ # cloud-finops-mcp
2
+
3
+ MCP server exposing the [OptimNow Cloud FinOps skill](https://github.com/OptimNow/cloud-finops-skills)
4
+ (28 reference files + 15 named-pattern playbooks) as queryable tools for any
5
+ MCP-aware client (Claude Code, Cursor, Codex CLI, Windsurf, Aider, Cline, etc.).
6
+
7
+ The skill itself ships in canonical Claude Agent-Skills format and is also installable
8
+ via the cross-tool installer (`./install.sh`) for direct context injection. This MCP
9
+ server is the **enrichment path**: instead of loading the full skill into the
10
+ prompt, the agent calls tools to discover, filter, and fetch only what it needs.
11
+
12
+ ## What the server exposes
13
+
14
+ Six tools, all read-only, split across two surfaces.
15
+
16
+ **References** — long-form provider and discipline files (~300-500 lines each):
17
+
18
+ | Tool | Purpose |
19
+ |---|---|
20
+ | `list_references()` | List all 28 references with their FCP metadata. |
21
+ | `get_reference(name)` | Fetch the full markdown body of one reference. |
22
+ | `find_references(domain?, capability?, phase?, persona?, maturity?)` | Faceted query over the FinOps Capability/Phase frontmatter. |
23
+
24
+ The reference faceted query supports any combination of:
25
+
26
+ - `domain` - FinOps Framework domain (e.g. `Optimize Usage & Cost`, `Quantify Business Value`)
27
+ - `capability` - FinOps capability (matches both primary and secondary)
28
+ - `phase` - `Inform`, `Optimize`, `Operate`
29
+ - `persona` - matches both primary and collaborating personas
30
+ - `maturity` - `Crawl`, `Walk`, `Run`
31
+
32
+ **Playbooks** — small named-pattern runbooks (~80-130 lines each):
33
+
34
+ | Tool | Purpose |
35
+ |---|---|
36
+ | `list_playbooks()` | List all 15 named-pattern playbooks with their metadata. |
37
+ | `get_playbook(name)` | Fetch the full markdown body of one playbook. |
38
+ | `find_playbooks(scope?, service?, waste_category?, confidence?)` | Faceted query over the playbook frontmatter. |
39
+
40
+ The playbook faceted query supports:
41
+
42
+ - `scope` - `aws`, `azure`, `gcp`, or `cross-cloud`
43
+ - `service` - provider service (e.g. `AWS NAT Gateway`); exact-match
44
+ - `waste_category` - `orphaned`, `idle`, `overprovisioned`, `commitment-mismatch`,
45
+ `schedule-blindness`, `modernization`, `ai-ml-inefficiency`, `egress`
46
+ - `confidence` - `obvious`, `likely`, `possible` (OptimNow three-tier model)
47
+
48
+ All filters across both surfaces AND together. String matches are case-insensitive
49
+ and exact (no substring matching).
50
+
51
+ **When to use which surface:**
52
+
53
+ - A **playbook** answers *"how do I detect/fix this specific pattern?"* (zombie NAT,
54
+ snapshot sprawl, idle ELB). It includes problem statement, symptoms, a detection
55
+ query (CUR / KQL / BigQuery SQL / CLI), fix steps, and the anti-pattern.
56
+ - A **reference** answers anything broader: billing mechanics, commitment strategy,
57
+ allocation methodology, persona-specific framings, or cross-pattern reasoning.
58
+
59
+ ## Install
60
+
61
+ ```bash
62
+ pip install cloud-finops-mcp
63
+ ```
64
+
65
+ Or run without installing via [`uv`](https://docs.astral.sh/uv/):
66
+
67
+ ```bash
68
+ uvx cloud-finops-mcp
69
+ ```
70
+
71
+ ## Configure your MCP client
72
+
73
+ After install, point your client at the `cloud-finops-mcp` console script.
74
+
75
+ ### Claude Code
76
+
77
+ Project-level (`.mcp.json` at the repo root) or user-level (`~/.claude/mcp.json`):
78
+
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "cloud-finops": {
83
+ "command": "cloud-finops-mcp"
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ Restart Claude Code, then run `/mcp` to confirm the server is connected.
90
+
91
+ ### Cursor
92
+
93
+ `~/.cursor/mcp.json`:
94
+
95
+ ```json
96
+ {
97
+ "mcpServers": {
98
+ "cloud-finops": {
99
+ "command": "cloud-finops-mcp"
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ ### Codex CLI
106
+
107
+ `~/.codex/config.toml`:
108
+
109
+ ```toml
110
+ [mcp_servers.cloud-finops]
111
+ command = "cloud-finops-mcp"
112
+ ```
113
+
114
+ ### Windsurf
115
+
116
+ `~/.windsurf/mcp.json`:
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "cloud-finops": {
122
+ "command": "cloud-finops-mcp"
123
+ }
124
+ }
125
+ }
126
+ ```
127
+
128
+ ### Any other MCP client
129
+
130
+ The server speaks MCP over stdio. Point any compatible client at `cloud-finops-mcp`
131
+ (or `python -m cloud_finops_mcp`).
132
+
133
+ ## Example tool calls
134
+
135
+ Agent prompt: *"Use the cloud-finops MCP to find references for the Optimize phase
136
+ aimed at Engineering."*
137
+
138
+ Calls `find_references(phase="Optimize", persona="Engineering")` and gets back the
139
+ filtered subset (AWS, Azure, GCP, Bedrock, Databricks, etc.) without loading the full
140
+ skill into the prompt.
141
+
142
+ Agent prompt: *"Pull the AWS reference."*
143
+
144
+ Calls `get_reference(name="finops-aws")` and gets back the full markdown body
145
+ (~300 lines) instead of the entire 28-file knowledge base.
146
+
147
+ Agent prompt: *"Show me the obvious-confidence AWS waste playbooks."*
148
+
149
+ Calls `find_playbooks(scope="aws", confidence="obvious")` and gets back the list
150
+ of high-signal AWS patterns (zombie NAT gateway, orphaned EBS volumes, etc.).
151
+
152
+ Agent prompt: *"Walk me through the zombie NAT gateway pattern."*
153
+
154
+ Calls `get_playbook(name="aws-zombie-nat-gateway")` and gets back the ~90-line
155
+ runbook (problem, symptoms, detection query, fix, anti-pattern, see-also).
156
+
157
+ ## When to use this vs the installer
158
+
159
+ | If you... | Use |
160
+ |---|---|
161
+ | Want the skill loaded as static context for every chat | The cross-tool installer (`./install.sh`) |
162
+ | Have a big-codebase session with limited context budget | The MCP server (fetch on demand) |
163
+ | Want to filter references by FinOps domain/capability/phase/persona/maturity | The MCP server (`find_references`) |
164
+ | Use a client that doesn't support MCP | The cross-tool installer |
165
+
166
+ The two paths are complementary. You can install both.
167
+
168
+ ## Development
169
+
170
+ ```bash
171
+ git clone https://github.com/OptimNow/cloud-finops-skills.git
172
+ cd cloud-finops-skills/mcp_server
173
+ python scripts/sync_references.py # populate src/cloud_finops_mcp/data/
174
+ pip install -e ".[dev]"
175
+ pytest
176
+ ```
177
+
178
+ ## Versioning
179
+
180
+ The PyPI package version tracks the skill release tag. Tagging `v1.13` on the
181
+ parent repo triggers both the skill release zip and a new `cloud-finops-mcp` PyPI
182
+ publish so the bundled references match what the rest of the repo ships.
183
+
184
+ ## License
185
+
186
+ [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) - same as the parent
187
+ skill. Credit OptimNow.
@@ -0,0 +1,86 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.18", "hatch-build-scripts>=0.0.4"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cloud-finops-mcp"
7
+ version = "1.21.0"
8
+ description = "MCP server exposing the OptimNow Cloud FinOps skill (28 references) as queryable tools."
9
+ readme = "README.md"
10
+ license = { text = "CC-BY-SA-4.0" }
11
+ authors = [
12
+ { name = "OptimNow", email = "contact@optimnow.io" }
13
+ ]
14
+ maintainers = [
15
+ { name = "Jean Latière", email = "j.latiere@gmail.com" }
16
+ ]
17
+ requires-python = ">=3.10"
18
+ keywords = ["finops", "cloud", "cost", "mcp", "claude", "aws", "azure", "gcp"]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "Intended Audience :: Information Technology",
23
+ "License :: OSI Approved",
24
+ "Operating System :: OS Independent",
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Topic :: Software Development :: Libraries :: Python Modules",
30
+ ]
31
+ dependencies = [
32
+ "mcp>=1.0.0",
33
+ "pyyaml>=6.0",
34
+ ]
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=7.4",
39
+ "pytest-asyncio>=0.23",
40
+ "ruff>=0.5",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/OptimNow/cloud-finops-skills"
45
+ Repository = "https://github.com/OptimNow/cloud-finops-skills"
46
+ Issues = "https://github.com/OptimNow/cloud-finops-skills/issues"
47
+ Documentation = "https://github.com/OptimNow/cloud-finops-skills/tree/main/mcp_server"
48
+
49
+ [project.scripts]
50
+ cloud-finops-mcp = "cloud_finops_mcp.__main__:main"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/cloud_finops_mcp"]
54
+ # .md files in src/cloud_finops_mcp/data/ are gitignored but live in the
55
+ # package directory; hatch picks them up via the package walk, no
56
+ # force-include needed.
57
+
58
+ [tool.hatch.build.targets.sdist]
59
+ include = [
60
+ "src/cloud_finops_mcp",
61
+ "scripts",
62
+ "tests",
63
+ "README.md",
64
+ "pyproject.toml",
65
+ ]
66
+ # Force-include the synced reference bundle so the sdist is self-contained -
67
+ # without this, hatch respects ../../.gitignore and drops src/.../data/*.md.
68
+ [tool.hatch.build.targets.sdist.force-include]
69
+ "src/cloud_finops_mcp/data" = "src/cloud_finops_mcp/data"
70
+
71
+ [[tool.hatch.build.hooks.build-scripts.scripts]]
72
+ out_dir = "src/cloud_finops_mcp/data"
73
+ commands = ["python scripts/sync_references.py"]
74
+ artifacts = []
75
+
76
+ [tool.pytest.ini_options]
77
+ testpaths = ["tests"]
78
+ asyncio_mode = "auto"
79
+
80
+ [tool.ruff]
81
+ line-length = 100
82
+ target-version = "py310"
83
+
84
+ [tool.ruff.lint]
85
+ select = ["E", "F", "I", "W", "UP"]
86
+ ignore = ["E501"]
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env python3
2
+ """Copy ``cloud-finops/references/*.md`` and ``cloud-finops/playbooks/*.md`` into
3
+ the bundled ``data/`` folder.
4
+
5
+ Runs automatically before each wheel build (declared in ``pyproject.toml`` as a
6
+ ``hatch-build-scripts`` hook). Also intended to be run manually after
7
+ ``pip install -e .`` so the editable install picks up the latest reference
8
+ content::
9
+
10
+ python scripts/sync_references.py
11
+
12
+ The script is idempotent and clears the destination folders first to drop
13
+ files that have been removed upstream. The ``playbooks/README.md`` file is
14
+ intentionally skipped: it documents the format for human contributors and is
15
+ not a runbook the agent should retrieve.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import shutil
21
+ import sys
22
+ from pathlib import Path
23
+
24
+ REPO_ROOT = Path(__file__).resolve().parents[2]
25
+ REFERENCES_SRC = REPO_ROOT / "cloud-finops" / "references"
26
+ PLAYBOOKS_SRC = REPO_ROOT / "cloud-finops" / "playbooks"
27
+
28
+ DATA_ROOT = Path(__file__).resolve().parents[1] / "src" / "cloud_finops_mcp" / "data"
29
+ REFERENCES_DEST = DATA_ROOT
30
+ PLAYBOOKS_DEST = DATA_ROOT / "playbooks"
31
+
32
+
33
+ def _sync(label: str, src_dir: Path, dest_dir: Path, *, skip: set[str]) -> int:
34
+ """Mirror ``*.md`` from ``src_dir`` into ``dest_dir``.
35
+
36
+ Returns the number of files copied. Falls back gracefully when ``src_dir`` is
37
+ missing (sdist-build case) but ``dest_dir`` is already populated.
38
+ """
39
+ dest_dir.mkdir(parents=True, exist_ok=True)
40
+ existing = [p for p in dest_dir.glob("*.md")]
41
+
42
+ if not src_dir.is_dir():
43
+ if existing:
44
+ print(
45
+ f"[sync_references] {label}: source missing; using "
46
+ f"{len(existing)} pre-bundled file(s) at {dest_dir}"
47
+ )
48
+ return len(existing)
49
+ print(
50
+ f"[sync_references] {label}: source directory not found and no "
51
+ f"pre-bundled files present: {src_dir}",
52
+ file=sys.stderr,
53
+ )
54
+ return -1
55
+
56
+ # Wipe stale .md files so deletions upstream propagate to the bundle.
57
+ for stale in existing:
58
+ stale.unlink()
59
+
60
+ copied = 0
61
+ for src in sorted(src_dir.glob("*.md")):
62
+ if src.name in skip:
63
+ continue
64
+ shutil.copy2(src, dest_dir / src.name)
65
+ copied += 1
66
+
67
+ print(f"[sync_references] {label}: copied {copied} file(s) to {dest_dir}")
68
+ return copied
69
+
70
+
71
+ def main() -> int:
72
+ refs = _sync("references", REFERENCES_SRC, REFERENCES_DEST, skip=set())
73
+ playbooks = _sync(
74
+ "playbooks", PLAYBOOKS_SRC, PLAYBOOKS_DEST, skip={"README.md"}
75
+ )
76
+
77
+ if refs < 0:
78
+ return 1
79
+ if playbooks < 0:
80
+ # Playbooks are optional - older skill versions may not have shipped
81
+ # them. Warn but do not fail the build.
82
+ print(
83
+ "[sync_references] WARNING: playbooks unavailable; the MCP "
84
+ "server will still expose references but list_playbooks() will "
85
+ "be empty.",
86
+ file=sys.stderr,
87
+ )
88
+ return 0
89
+
90
+
91
+ if __name__ == "__main__":
92
+ raise SystemExit(main())
@@ -0,0 +1,14 @@
1
+ """Cloud FinOps MCP server.
2
+
3
+ Exposes the OptimNow Cloud FinOps skill (28 references) as queryable tools
4
+ via the Model Context Protocol.
5
+ """
6
+
7
+ from importlib.metadata import PackageNotFoundError, version
8
+
9
+ try:
10
+ __version__ = version("cloud-finops-mcp")
11
+ except PackageNotFoundError: # pragma: no cover - editable / not installed
12
+ __version__ = "0.0.0+dev"
13
+
14
+ __all__ = ["__version__"]
@@ -0,0 +1,16 @@
1
+ """Entry point: ``python -m cloud_finops_mcp`` and ``cloud-finops-mcp`` console script."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+
7
+ from .server import run
8
+
9
+
10
+ def main() -> None:
11
+ """Synchronous wrapper used by the console-script entry point."""
12
+ asyncio.run(run())
13
+
14
+
15
+ if __name__ == "__main__":
16
+ main()
@@ -0,0 +1,3 @@
1
+ # Bundled reference content is generated by scripts/sync_references.py.
2
+ # Source of truth lives at ../../../cloud-finops/references/.
3
+ *.md