foundry-mcp 0.3.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- foundry_mcp/__init__.py +7 -0
- foundry_mcp/cli/__init__.py +80 -0
- foundry_mcp/cli/__main__.py +9 -0
- foundry_mcp/cli/agent.py +96 -0
- foundry_mcp/cli/commands/__init__.py +37 -0
- foundry_mcp/cli/commands/cache.py +137 -0
- foundry_mcp/cli/commands/dashboard.py +148 -0
- foundry_mcp/cli/commands/dev.py +446 -0
- foundry_mcp/cli/commands/journal.py +377 -0
- foundry_mcp/cli/commands/lifecycle.py +274 -0
- foundry_mcp/cli/commands/modify.py +824 -0
- foundry_mcp/cli/commands/plan.py +633 -0
- foundry_mcp/cli/commands/pr.py +393 -0
- foundry_mcp/cli/commands/review.py +652 -0
- foundry_mcp/cli/commands/session.py +479 -0
- foundry_mcp/cli/commands/specs.py +856 -0
- foundry_mcp/cli/commands/tasks.py +807 -0
- foundry_mcp/cli/commands/testing.py +676 -0
- foundry_mcp/cli/commands/validate.py +982 -0
- foundry_mcp/cli/config.py +98 -0
- foundry_mcp/cli/context.py +259 -0
- foundry_mcp/cli/flags.py +266 -0
- foundry_mcp/cli/logging.py +212 -0
- foundry_mcp/cli/main.py +44 -0
- foundry_mcp/cli/output.py +122 -0
- foundry_mcp/cli/registry.py +110 -0
- foundry_mcp/cli/resilience.py +178 -0
- foundry_mcp/cli/transcript.py +217 -0
- foundry_mcp/config.py +850 -0
- foundry_mcp/core/__init__.py +144 -0
- foundry_mcp/core/ai_consultation.py +1636 -0
- foundry_mcp/core/cache.py +195 -0
- foundry_mcp/core/capabilities.py +446 -0
- foundry_mcp/core/concurrency.py +898 -0
- foundry_mcp/core/context.py +540 -0
- foundry_mcp/core/discovery.py +1603 -0
- foundry_mcp/core/error_collection.py +728 -0
- foundry_mcp/core/error_store.py +592 -0
- foundry_mcp/core/feature_flags.py +592 -0
- foundry_mcp/core/health.py +749 -0
- foundry_mcp/core/journal.py +694 -0
- foundry_mcp/core/lifecycle.py +412 -0
- foundry_mcp/core/llm_config.py +1350 -0
- foundry_mcp/core/llm_patterns.py +510 -0
- foundry_mcp/core/llm_provider.py +1569 -0
- foundry_mcp/core/logging_config.py +374 -0
- foundry_mcp/core/metrics_persistence.py +584 -0
- foundry_mcp/core/metrics_registry.py +327 -0
- foundry_mcp/core/metrics_store.py +641 -0
- foundry_mcp/core/modifications.py +224 -0
- foundry_mcp/core/naming.py +123 -0
- foundry_mcp/core/observability.py +1216 -0
- foundry_mcp/core/otel.py +452 -0
- foundry_mcp/core/otel_stubs.py +264 -0
- foundry_mcp/core/pagination.py +255 -0
- foundry_mcp/core/progress.py +317 -0
- foundry_mcp/core/prometheus.py +577 -0
- foundry_mcp/core/prompts/__init__.py +464 -0
- foundry_mcp/core/prompts/fidelity_review.py +546 -0
- foundry_mcp/core/prompts/markdown_plan_review.py +511 -0
- foundry_mcp/core/prompts/plan_review.py +623 -0
- foundry_mcp/core/providers/__init__.py +225 -0
- foundry_mcp/core/providers/base.py +476 -0
- foundry_mcp/core/providers/claude.py +460 -0
- foundry_mcp/core/providers/codex.py +619 -0
- foundry_mcp/core/providers/cursor_agent.py +642 -0
- foundry_mcp/core/providers/detectors.py +488 -0
- foundry_mcp/core/providers/gemini.py +405 -0
- foundry_mcp/core/providers/opencode.py +616 -0
- foundry_mcp/core/providers/opencode_wrapper.js +302 -0
- foundry_mcp/core/providers/package-lock.json +24 -0
- foundry_mcp/core/providers/package.json +25 -0
- foundry_mcp/core/providers/registry.py +607 -0
- foundry_mcp/core/providers/test_provider.py +171 -0
- foundry_mcp/core/providers/validation.py +729 -0
- foundry_mcp/core/rate_limit.py +427 -0
- foundry_mcp/core/resilience.py +600 -0
- foundry_mcp/core/responses.py +934 -0
- foundry_mcp/core/review.py +366 -0
- foundry_mcp/core/security.py +438 -0
- foundry_mcp/core/spec.py +1650 -0
- foundry_mcp/core/task.py +1289 -0
- foundry_mcp/core/testing.py +450 -0
- foundry_mcp/core/validation.py +2081 -0
- foundry_mcp/dashboard/__init__.py +32 -0
- foundry_mcp/dashboard/app.py +119 -0
- foundry_mcp/dashboard/components/__init__.py +17 -0
- foundry_mcp/dashboard/components/cards.py +88 -0
- foundry_mcp/dashboard/components/charts.py +234 -0
- foundry_mcp/dashboard/components/filters.py +136 -0
- foundry_mcp/dashboard/components/tables.py +195 -0
- foundry_mcp/dashboard/data/__init__.py +11 -0
- foundry_mcp/dashboard/data/stores.py +433 -0
- foundry_mcp/dashboard/launcher.py +289 -0
- foundry_mcp/dashboard/views/__init__.py +12 -0
- foundry_mcp/dashboard/views/errors.py +217 -0
- foundry_mcp/dashboard/views/metrics.py +174 -0
- foundry_mcp/dashboard/views/overview.py +160 -0
- foundry_mcp/dashboard/views/providers.py +83 -0
- foundry_mcp/dashboard/views/sdd_workflow.py +255 -0
- foundry_mcp/dashboard/views/tool_usage.py +139 -0
- foundry_mcp/prompts/__init__.py +9 -0
- foundry_mcp/prompts/workflows.py +525 -0
- foundry_mcp/resources/__init__.py +9 -0
- foundry_mcp/resources/specs.py +591 -0
- foundry_mcp/schemas/__init__.py +38 -0
- foundry_mcp/schemas/sdd-spec-schema.json +386 -0
- foundry_mcp/server.py +164 -0
- foundry_mcp/tools/__init__.py +10 -0
- foundry_mcp/tools/unified/__init__.py +71 -0
- foundry_mcp/tools/unified/authoring.py +1487 -0
- foundry_mcp/tools/unified/context_helpers.py +98 -0
- foundry_mcp/tools/unified/documentation_helpers.py +198 -0
- foundry_mcp/tools/unified/environment.py +939 -0
- foundry_mcp/tools/unified/error.py +462 -0
- foundry_mcp/tools/unified/health.py +225 -0
- foundry_mcp/tools/unified/journal.py +841 -0
- foundry_mcp/tools/unified/lifecycle.py +632 -0
- foundry_mcp/tools/unified/metrics.py +777 -0
- foundry_mcp/tools/unified/plan.py +745 -0
- foundry_mcp/tools/unified/pr.py +294 -0
- foundry_mcp/tools/unified/provider.py +629 -0
- foundry_mcp/tools/unified/review.py +685 -0
- foundry_mcp/tools/unified/review_helpers.py +299 -0
- foundry_mcp/tools/unified/router.py +102 -0
- foundry_mcp/tools/unified/server.py +580 -0
- foundry_mcp/tools/unified/spec.py +808 -0
- foundry_mcp/tools/unified/task.py +2202 -0
- foundry_mcp/tools/unified/test.py +370 -0
- foundry_mcp/tools/unified/verification.py +520 -0
- foundry_mcp-0.3.3.dist-info/METADATA +337 -0
- foundry_mcp-0.3.3.dist-info/RECORD +135 -0
- foundry_mcp-0.3.3.dist-info/WHEEL +4 -0
- foundry_mcp-0.3.3.dist-info/entry_points.txt +3 -0
- foundry_mcp-0.3.3.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "SDD Spec File Schema",
|
|
4
|
+
"description": "Schema for SDD (Spec-Driven Development) JSON specification files",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": [
|
|
7
|
+
"spec_id",
|
|
8
|
+
"generated",
|
|
9
|
+
"last_updated",
|
|
10
|
+
"hierarchy"
|
|
11
|
+
],
|
|
12
|
+
"properties": {
|
|
13
|
+
"spec_id": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"pattern": "^[\\w-]+-\\d{4}-\\d{2}-\\d{2}-\\d{3}$",
|
|
16
|
+
"description": "Unique specification identifier: {feature}-{YYYY-MM-DD}-{nnn}"
|
|
17
|
+
},
|
|
18
|
+
"title": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"minLength": 1,
|
|
21
|
+
"description": "Human-readable specification title"
|
|
22
|
+
},
|
|
23
|
+
"generated": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"format": "date-time",
|
|
26
|
+
"description": "ISO 8601 timestamp when spec was generated"
|
|
27
|
+
},
|
|
28
|
+
"last_updated": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"format": "date-time",
|
|
31
|
+
"description": "ISO 8601 timestamp of last update"
|
|
32
|
+
},
|
|
33
|
+
"metadata": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"description": "Optional spec-level metadata",
|
|
36
|
+
"properties": {
|
|
37
|
+
"title": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"description": "Specification title retained for backward compatibility."
|
|
40
|
+
},
|
|
41
|
+
"description": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"description": "High-level description of the specification."
|
|
44
|
+
},
|
|
45
|
+
"objectives": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": {
|
|
48
|
+
"type": "string"
|
|
49
|
+
},
|
|
50
|
+
"description": "Key objectives or acceptance criteria for the spec."
|
|
51
|
+
},
|
|
52
|
+
"complexity": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"description": "Relative complexity indicator."
|
|
55
|
+
},
|
|
56
|
+
"estimated_hours": {
|
|
57
|
+
"type": "number",
|
|
58
|
+
"minimum": 0
|
|
59
|
+
},
|
|
60
|
+
"owner": {
|
|
61
|
+
"type": "string"
|
|
62
|
+
},
|
|
63
|
+
"status": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Workflow status for the specification."
|
|
66
|
+
},
|
|
67
|
+
"assumptions": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"items": {
|
|
70
|
+
"type": "string"
|
|
71
|
+
},
|
|
72
|
+
"description": "Design assumptions and constraints for this spec (e.g., single-user workflow, feature branch ownership)"
|
|
73
|
+
},
|
|
74
|
+
"revision_history": {
|
|
75
|
+
"type": "array",
|
|
76
|
+
"items": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"required": [
|
|
79
|
+
"version",
|
|
80
|
+
"date",
|
|
81
|
+
"changelog"
|
|
82
|
+
],
|
|
83
|
+
"properties": {
|
|
84
|
+
"version": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"description": "Version number (e.g., 1.0, 1.1, 2.0)"
|
|
87
|
+
},
|
|
88
|
+
"date": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"format": "date-time",
|
|
91
|
+
"description": "ISO 8601 timestamp of revision"
|
|
92
|
+
},
|
|
93
|
+
"author": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "Who made the revision"
|
|
96
|
+
},
|
|
97
|
+
"changelog": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"description": "Description of changes made in this revision"
|
|
100
|
+
},
|
|
101
|
+
"modified_by": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "Tool or command that made the modification (e.g., sdd modify-spec)"
|
|
104
|
+
},
|
|
105
|
+
"review_triggered_by": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"description": "Path to review report that triggered this revision (if applicable)"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"description": "Version history tracking spec modifications over time"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"additionalProperties": true
|
|
115
|
+
},
|
|
116
|
+
"hierarchy": {
|
|
117
|
+
"type": "object",
|
|
118
|
+
"description": "Task hierarchy tree",
|
|
119
|
+
"patternProperties": {
|
|
120
|
+
"^spec-root$": {
|
|
121
|
+
"$ref": "#/definitions/node"
|
|
122
|
+
},
|
|
123
|
+
"^phase-\\d+(?:-[\\w-]+)*$": {
|
|
124
|
+
"$ref": "#/definitions/node"
|
|
125
|
+
},
|
|
126
|
+
"^task-\\d+(?:-\\d+)+$": {
|
|
127
|
+
"$ref": "#/definitions/node"
|
|
128
|
+
},
|
|
129
|
+
"^verify-\\d+(?:-\\d+)+$": {
|
|
130
|
+
"$ref": "#/definitions/node"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"definitions": {
|
|
136
|
+
"node": {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"required": [
|
|
139
|
+
"type",
|
|
140
|
+
"title",
|
|
141
|
+
"status",
|
|
142
|
+
"parent",
|
|
143
|
+
"children",
|
|
144
|
+
"total_tasks",
|
|
145
|
+
"completed_tasks",
|
|
146
|
+
"metadata"
|
|
147
|
+
],
|
|
148
|
+
"properties": {
|
|
149
|
+
"id": {
|
|
150
|
+
"type": "string",
|
|
151
|
+
"description": "Node identifier matching the key in hierarchy"
|
|
152
|
+
},
|
|
153
|
+
"type": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"enum": [
|
|
156
|
+
"spec",
|
|
157
|
+
"phase",
|
|
158
|
+
"group",
|
|
159
|
+
"task",
|
|
160
|
+
"subtask",
|
|
161
|
+
"verify"
|
|
162
|
+
],
|
|
163
|
+
"description": "Node type in hierarchy"
|
|
164
|
+
},
|
|
165
|
+
"title": {
|
|
166
|
+
"type": "string",
|
|
167
|
+
"minLength": 1,
|
|
168
|
+
"description": "Human-readable title"
|
|
169
|
+
},
|
|
170
|
+
"status": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"enum": [
|
|
173
|
+
"pending",
|
|
174
|
+
"in_progress",
|
|
175
|
+
"completed",
|
|
176
|
+
"blocked"
|
|
177
|
+
],
|
|
178
|
+
"description": "Current status"
|
|
179
|
+
},
|
|
180
|
+
"parent": {
|
|
181
|
+
"type": [
|
|
182
|
+
"string",
|
|
183
|
+
"null"
|
|
184
|
+
],
|
|
185
|
+
"description": "Parent node ID (null only for spec-root)"
|
|
186
|
+
},
|
|
187
|
+
"children": {
|
|
188
|
+
"type": "array",
|
|
189
|
+
"items": {
|
|
190
|
+
"type": "string"
|
|
191
|
+
},
|
|
192
|
+
"description": "Array of child node IDs"
|
|
193
|
+
},
|
|
194
|
+
"metadata": {
|
|
195
|
+
"type": "object",
|
|
196
|
+
"description": "Node-specific metadata",
|
|
197
|
+
"default": {},
|
|
198
|
+
"properties": {
|
|
199
|
+
"purpose": {
|
|
200
|
+
"type": "string",
|
|
201
|
+
"description": "High-level intent or goal for the node's work."
|
|
202
|
+
},
|
|
203
|
+
"risk_level": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"description": "Qualitative risk indicator (e.g., low, medium, high)."
|
|
206
|
+
},
|
|
207
|
+
"estimated_hours": {
|
|
208
|
+
"type": "number",
|
|
209
|
+
"minimum": 0
|
|
210
|
+
},
|
|
211
|
+
"complexity": {
|
|
212
|
+
"type": "string",
|
|
213
|
+
"description": "Relative complexity label."
|
|
214
|
+
},
|
|
215
|
+
"task_category": {
|
|
216
|
+
"type": "string",
|
|
217
|
+
"enum": [
|
|
218
|
+
"investigation",
|
|
219
|
+
"implementation",
|
|
220
|
+
"refactoring",
|
|
221
|
+
"decision",
|
|
222
|
+
"research"
|
|
223
|
+
],
|
|
224
|
+
"description": "Category of task work."
|
|
225
|
+
},
|
|
226
|
+
"file_path": {
|
|
227
|
+
"type": "string",
|
|
228
|
+
"description": "Primary file impacted by the node."
|
|
229
|
+
},
|
|
230
|
+
"details": {
|
|
231
|
+
"oneOf": [
|
|
232
|
+
{"type": "string"},
|
|
233
|
+
{
|
|
234
|
+
"type": "array",
|
|
235
|
+
"items": {"type": "string"}
|
|
236
|
+
}
|
|
237
|
+
],
|
|
238
|
+
"description": "Free-form detail text for subtasks and tasks. Can be a string or array of strings."
|
|
239
|
+
},
|
|
240
|
+
"changes": {
|
|
241
|
+
"type": "string",
|
|
242
|
+
"description": "Summary of expected code or documentation changes."
|
|
243
|
+
},
|
|
244
|
+
"reasoning": {
|
|
245
|
+
"type": "string",
|
|
246
|
+
"description": "Supporting rationale or justification."
|
|
247
|
+
},
|
|
248
|
+
"owner": {
|
|
249
|
+
"type": "string",
|
|
250
|
+
"description": "Optional owner or assignee."
|
|
251
|
+
},
|
|
252
|
+
"verification_type": {
|
|
253
|
+
"type": "string",
|
|
254
|
+
"enum": [
|
|
255
|
+
"run-tests",
|
|
256
|
+
"fidelity"
|
|
257
|
+
]
|
|
258
|
+
},
|
|
259
|
+
"agent": {
|
|
260
|
+
"type": "string",
|
|
261
|
+
"description": "Automation agent to run for verification."
|
|
262
|
+
},
|
|
263
|
+
"mcp_tool": {
|
|
264
|
+
"type": "string",
|
|
265
|
+
"description": "MCP tool to invoke for verification (e.g., mcp__foundry-mcp__spec-review-fidelity)."
|
|
266
|
+
},
|
|
267
|
+
"command": {
|
|
268
|
+
"type": "string",
|
|
269
|
+
"description": "Command or instructions for automated verification."
|
|
270
|
+
},
|
|
271
|
+
"expected": {
|
|
272
|
+
"type": "string",
|
|
273
|
+
"description": "Expected outcome of verification."
|
|
274
|
+
},
|
|
275
|
+
"scope": {
|
|
276
|
+
"type": "string",
|
|
277
|
+
"description": "Scope identifier for fidelity verification."
|
|
278
|
+
},
|
|
279
|
+
"target": {
|
|
280
|
+
"type": "string",
|
|
281
|
+
"description": "Target identifier for verification scope."
|
|
282
|
+
},
|
|
283
|
+
"status": {
|
|
284
|
+
"type": "string",
|
|
285
|
+
"description": "Optional workflow status for metadata (distinct from node status)."
|
|
286
|
+
},
|
|
287
|
+
"started_at": {
|
|
288
|
+
"type": "string",
|
|
289
|
+
"format": "date-time",
|
|
290
|
+
"description": "ISO 8601 timestamp when work started."
|
|
291
|
+
},
|
|
292
|
+
"completed_at": {
|
|
293
|
+
"type": "string",
|
|
294
|
+
"format": "date-time",
|
|
295
|
+
"description": "ISO 8601 timestamp when work completed."
|
|
296
|
+
},
|
|
297
|
+
"actual_hours": {
|
|
298
|
+
"type": "number",
|
|
299
|
+
"minimum": 0,
|
|
300
|
+
"description": "Actual hours spent on the node."
|
|
301
|
+
},
|
|
302
|
+
"on_failure": {
|
|
303
|
+
"$ref": "#/definitions/on_failure_actions"
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
"additionalProperties": true
|
|
307
|
+
},
|
|
308
|
+
"total_tasks": {
|
|
309
|
+
"type": "integer",
|
|
310
|
+
"minimum": 0,
|
|
311
|
+
"description": "Total tasks in this subtree"
|
|
312
|
+
},
|
|
313
|
+
"completed_tasks": {
|
|
314
|
+
"type": "integer",
|
|
315
|
+
"minimum": 0,
|
|
316
|
+
"description": "Completed tasks in this subtree"
|
|
317
|
+
},
|
|
318
|
+
"dependencies": {
|
|
319
|
+
"type": "object",
|
|
320
|
+
"properties": {
|
|
321
|
+
"blocked_by": {
|
|
322
|
+
"type": "array",
|
|
323
|
+
"items": {
|
|
324
|
+
"type": "string"
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
"depends": {
|
|
328
|
+
"type": "array",
|
|
329
|
+
"items": {
|
|
330
|
+
"type": "string"
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
"blocks": {
|
|
334
|
+
"type": "array",
|
|
335
|
+
"items": {
|
|
336
|
+
"type": "string"
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"on_failure_actions": {
|
|
344
|
+
"type": "object",
|
|
345
|
+
"description": "Configurable actions to take when verification fails",
|
|
346
|
+
"properties": {
|
|
347
|
+
"consult": {
|
|
348
|
+
"type": "boolean",
|
|
349
|
+
"description": "Whether to trigger AI consultation for debugging (default: false)",
|
|
350
|
+
"default": false
|
|
351
|
+
},
|
|
352
|
+
"revert_status": {
|
|
353
|
+
"type": "string",
|
|
354
|
+
"enum": [
|
|
355
|
+
"pending",
|
|
356
|
+
"in_progress",
|
|
357
|
+
"blocked"
|
|
358
|
+
],
|
|
359
|
+
"description": "Status to revert the parent task to on failure (default: in_progress)",
|
|
360
|
+
"default": "in_progress"
|
|
361
|
+
},
|
|
362
|
+
"max_retries": {
|
|
363
|
+
"type": "integer",
|
|
364
|
+
"minimum": 0,
|
|
365
|
+
"maximum": 5,
|
|
366
|
+
"description": "Maximum number of automatic retry attempts (default: 0)",
|
|
367
|
+
"default": 0
|
|
368
|
+
},
|
|
369
|
+
"notify": {
|
|
370
|
+
"type": "string",
|
|
371
|
+
"enum": [
|
|
372
|
+
"log"
|
|
373
|
+
],
|
|
374
|
+
"description": "Notification method on failure (default: log)",
|
|
375
|
+
"default": "log"
|
|
376
|
+
},
|
|
377
|
+
"continue_on_failure": {
|
|
378
|
+
"type": "boolean",
|
|
379
|
+
"description": "Whether to continue with other verifications if this one fails (default: false)",
|
|
380
|
+
"default": false
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
"additionalProperties": false
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
foundry_mcp/server.py
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""FastMCP server for foundry-mcp.
|
|
2
|
+
|
|
3
|
+
This server exposes the unified 17-router tool surface described in
|
|
4
|
+
`mcp/capabilities_manifest.json`.
|
|
5
|
+
|
|
6
|
+
Note: Legacy per-tool-name MCP endpoints are intentionally not registered.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
from mcp.server.fastmcp import FastMCP
|
|
17
|
+
|
|
18
|
+
from foundry_mcp.config import ServerConfig, get_config
|
|
19
|
+
from foundry_mcp.core.observability import audit_log, get_observability_manager
|
|
20
|
+
from foundry_mcp.core.feature_flags import get_flag_service
|
|
21
|
+
from foundry_mcp.resources.specs import register_spec_resources
|
|
22
|
+
from foundry_mcp.prompts.workflows import register_workflow_prompts
|
|
23
|
+
from foundry_mcp.tools.unified import register_unified_tools
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _init_observability(config: ServerConfig) -> None:
|
|
29
|
+
"""Initialize the observability stack from server configuration."""
|
|
30
|
+
|
|
31
|
+
obs_config = config.observability
|
|
32
|
+
if not obs_config.enabled:
|
|
33
|
+
logger.debug("Observability disabled in configuration")
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
manager = get_observability_manager()
|
|
37
|
+
manager.initialize(obs_config)
|
|
38
|
+
|
|
39
|
+
tracing_status = "enabled" if manager.is_tracing_enabled() else "disabled"
|
|
40
|
+
metrics_status = "enabled" if manager.is_metrics_enabled() else "disabled"
|
|
41
|
+
logger.info(
|
|
42
|
+
"Observability initialized: tracing=%s, metrics=%s",
|
|
43
|
+
tracing_status,
|
|
44
|
+
metrics_status,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _init_error_collection(config: ServerConfig) -> None:
|
|
49
|
+
"""Initialize the error collection infrastructure."""
|
|
50
|
+
|
|
51
|
+
err_config = config.error_collection
|
|
52
|
+
if not err_config.enabled:
|
|
53
|
+
logger.debug("Error collection disabled in configuration")
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
from foundry_mcp.core.error_collection import get_error_collector
|
|
58
|
+
from foundry_mcp.core.error_store import get_error_store
|
|
59
|
+
|
|
60
|
+
storage_path = err_config.get_storage_path()
|
|
61
|
+
store = get_error_store(storage_path)
|
|
62
|
+
collector = get_error_collector()
|
|
63
|
+
collector.initialize(store, err_config)
|
|
64
|
+
logger.info("Error collection initialized: storage_path=%s", storage_path)
|
|
65
|
+
except Exception as exc:
|
|
66
|
+
# Don't fail server startup due to optional error collection
|
|
67
|
+
logger.warning("Failed to initialize error collection: %s", exc)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _init_metrics_persistence(config: ServerConfig) -> None:
|
|
71
|
+
"""Initialize the metrics persistence infrastructure."""
|
|
72
|
+
|
|
73
|
+
metrics_config = config.metrics_persistence
|
|
74
|
+
if not metrics_config.enabled:
|
|
75
|
+
logger.debug("Metrics persistence disabled in configuration")
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
from foundry_mcp.core.metrics_persistence import initialize_metrics_persistence
|
|
80
|
+
from foundry_mcp.core.metrics_store import get_metrics_store
|
|
81
|
+
|
|
82
|
+
collector = initialize_metrics_persistence(metrics_config)
|
|
83
|
+
if collector is None:
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
storage_path = metrics_config.get_storage_path()
|
|
87
|
+
store = get_metrics_store(storage_path)
|
|
88
|
+
deleted_count = store.cleanup(
|
|
89
|
+
retention_days=metrics_config.retention_days,
|
|
90
|
+
max_records=metrics_config.max_records,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if deleted_count > 0:
|
|
94
|
+
logger.info("Metrics cleanup: removed %s old records", deleted_count)
|
|
95
|
+
|
|
96
|
+
logger.info("Metrics persistence initialized: storage_path=%s", storage_path)
|
|
97
|
+
except Exception as exc:
|
|
98
|
+
# Don't fail server startup due to optional persistence
|
|
99
|
+
logger.warning("Failed to initialize metrics persistence: %s", exc)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _apply_feature_flag_overrides_from_env() -> None:
|
|
103
|
+
"""Apply comma-separated feature flag overrides from `FEATURE_FLAGS`."""
|
|
104
|
+
|
|
105
|
+
raw = os.environ.get("FEATURE_FLAGS")
|
|
106
|
+
if not raw:
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
flag_service = get_flag_service()
|
|
110
|
+
for name in [part.strip() for part in raw.split(",") if part.strip()]:
|
|
111
|
+
flag_service.set_override("anonymous", name, True)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def create_server(config: Optional[ServerConfig] = None) -> FastMCP:
|
|
115
|
+
"""Create and configure the FastMCP server instance."""
|
|
116
|
+
|
|
117
|
+
if config is None:
|
|
118
|
+
config = get_config()
|
|
119
|
+
|
|
120
|
+
config.setup_logging()
|
|
121
|
+
|
|
122
|
+
_apply_feature_flag_overrides_from_env()
|
|
123
|
+
_init_observability(config)
|
|
124
|
+
_init_error_collection(config)
|
|
125
|
+
_init_metrics_persistence(config)
|
|
126
|
+
|
|
127
|
+
mcp = FastMCP(name=config.server_name)
|
|
128
|
+
|
|
129
|
+
# Unified-only tool surface
|
|
130
|
+
register_unified_tools(mcp, config)
|
|
131
|
+
|
|
132
|
+
# Resources and prompts
|
|
133
|
+
register_spec_resources(mcp, config)
|
|
134
|
+
register_workflow_prompts(mcp, config)
|
|
135
|
+
|
|
136
|
+
logger.info("Server created: %s v%s", config.server_name, config.server_version)
|
|
137
|
+
return mcp
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def main() -> None:
|
|
141
|
+
"""Main entry point for the foundry-mcp server."""
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
config = get_config()
|
|
145
|
+
server = create_server(config)
|
|
146
|
+
|
|
147
|
+
logger.info("Starting %s v%s", config.server_name, config.server_version)
|
|
148
|
+
audit_log("tool_invocation", tool="server_start", version=config.server_version)
|
|
149
|
+
|
|
150
|
+
server.run()
|
|
151
|
+
|
|
152
|
+
except KeyboardInterrupt:
|
|
153
|
+
logger.info("Server shutdown requested")
|
|
154
|
+
get_observability_manager().shutdown()
|
|
155
|
+
sys.exit(0)
|
|
156
|
+
except BaseException as exc:
|
|
157
|
+
logger.error("Server error: %s: %s", type(exc).__name__, exc)
|
|
158
|
+
audit_log("tool_invocation", tool="server_error", error=str(exc), success=False)
|
|
159
|
+
get_observability_manager().shutdown()
|
|
160
|
+
sys.exit(1)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
if __name__ == "__main__":
|
|
164
|
+
main()
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Unified action-based MCP tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from .authoring import register_unified_authoring_tool
|
|
8
|
+
from .error import register_unified_error_tool
|
|
9
|
+
from .health import register_unified_health_tool
|
|
10
|
+
from .journal import register_unified_journal_tool
|
|
11
|
+
from .metrics import register_unified_metrics_tool
|
|
12
|
+
from .plan import register_unified_plan_tool
|
|
13
|
+
from .pr import register_unified_pr_tool
|
|
14
|
+
from .provider import register_unified_provider_tool
|
|
15
|
+
from .environment import register_unified_environment_tool
|
|
16
|
+
from .lifecycle import register_unified_lifecycle_tool
|
|
17
|
+
from .verification import register_unified_verification_tool
|
|
18
|
+
from .review import register_unified_review_tool
|
|
19
|
+
from .spec import register_unified_spec_tool
|
|
20
|
+
from .server import register_unified_server_tool
|
|
21
|
+
from .test import register_unified_test_tool
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING: # pragma: no cover - import-time typing only
|
|
25
|
+
from mcp.server.fastmcp import FastMCP
|
|
26
|
+
from foundry_mcp.config import ServerConfig
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def register_unified_tools(mcp: "FastMCP", config: "ServerConfig") -> None:
|
|
30
|
+
"""Register consolidated tool families."""
|
|
31
|
+
|
|
32
|
+
register_unified_health_tool(mcp, config)
|
|
33
|
+
register_unified_plan_tool(mcp, config)
|
|
34
|
+
register_unified_pr_tool(mcp, config)
|
|
35
|
+
register_unified_error_tool(mcp, config)
|
|
36
|
+
register_unified_metrics_tool(mcp, config)
|
|
37
|
+
register_unified_journal_tool(mcp, config)
|
|
38
|
+
register_unified_authoring_tool(mcp, config)
|
|
39
|
+
register_unified_review_tool(mcp, config)
|
|
40
|
+
register_unified_spec_tool(mcp, config)
|
|
41
|
+
|
|
42
|
+
from importlib import import_module
|
|
43
|
+
|
|
44
|
+
_task_router = import_module("foundry_mcp.tools.unified.task")
|
|
45
|
+
_task_router.register_unified_task_tool(mcp, config)
|
|
46
|
+
register_unified_provider_tool(mcp, config)
|
|
47
|
+
register_unified_environment_tool(mcp, config)
|
|
48
|
+
register_unified_lifecycle_tool(mcp, config)
|
|
49
|
+
register_unified_verification_tool(mcp, config)
|
|
50
|
+
register_unified_server_tool(mcp, config)
|
|
51
|
+
register_unified_test_tool(mcp, config)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = [
|
|
55
|
+
"register_unified_tools",
|
|
56
|
+
"register_unified_health_tool",
|
|
57
|
+
"register_unified_plan_tool",
|
|
58
|
+
"register_unified_pr_tool",
|
|
59
|
+
"register_unified_error_tool",
|
|
60
|
+
"register_unified_metrics_tool",
|
|
61
|
+
"register_unified_journal_tool",
|
|
62
|
+
"register_unified_authoring_tool",
|
|
63
|
+
"register_unified_review_tool",
|
|
64
|
+
"register_unified_spec_tool",
|
|
65
|
+
"register_unified_provider_tool",
|
|
66
|
+
"register_unified_environment_tool",
|
|
67
|
+
"register_unified_lifecycle_tool",
|
|
68
|
+
"register_unified_verification_tool",
|
|
69
|
+
"register_unified_server_tool",
|
|
70
|
+
"register_unified_test_tool",
|
|
71
|
+
]
|