foundry-mcp 0.8.22__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.
Potentially problematic release.
This version of foundry-mcp might be problematic. Click here for more details.
- foundry_mcp/__init__.py +13 -0
- foundry_mcp/cli/__init__.py +67 -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 +640 -0
- foundry_mcp/cli/commands/pr.py +393 -0
- foundry_mcp/cli/commands/review.py +667 -0
- foundry_mcp/cli/commands/session.py +472 -0
- foundry_mcp/cli/commands/specs.py +686 -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 +298 -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 +1454 -0
- foundry_mcp/core/__init__.py +144 -0
- foundry_mcp/core/ai_consultation.py +1773 -0
- foundry_mcp/core/batch_operations.py +1202 -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/health.py +749 -0
- foundry_mcp/core/intake.py +933 -0
- foundry_mcp/core/journal.py +700 -0
- foundry_mcp/core/lifecycle.py +412 -0
- foundry_mcp/core/llm_config.py +1376 -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 +146 -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 +387 -0
- foundry_mcp/core/prometheus.py +564 -0
- foundry_mcp/core/prompts/__init__.py +464 -0
- foundry_mcp/core/prompts/fidelity_review.py +691 -0
- foundry_mcp/core/prompts/markdown_plan_review.py +515 -0
- foundry_mcp/core/prompts/plan_review.py +627 -0
- foundry_mcp/core/providers/__init__.py +237 -0
- foundry_mcp/core/providers/base.py +515 -0
- foundry_mcp/core/providers/claude.py +472 -0
- foundry_mcp/core/providers/codex.py +637 -0
- foundry_mcp/core/providers/cursor_agent.py +630 -0
- foundry_mcp/core/providers/detectors.py +515 -0
- foundry_mcp/core/providers/gemini.py +426 -0
- foundry_mcp/core/providers/opencode.py +718 -0
- foundry_mcp/core/providers/opencode_wrapper.js +308 -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 +857 -0
- foundry_mcp/core/rate_limit.py +427 -0
- foundry_mcp/core/research/__init__.py +68 -0
- foundry_mcp/core/research/memory.py +528 -0
- foundry_mcp/core/research/models.py +1234 -0
- foundry_mcp/core/research/providers/__init__.py +40 -0
- foundry_mcp/core/research/providers/base.py +242 -0
- foundry_mcp/core/research/providers/google.py +507 -0
- foundry_mcp/core/research/providers/perplexity.py +442 -0
- foundry_mcp/core/research/providers/semantic_scholar.py +544 -0
- foundry_mcp/core/research/providers/tavily.py +383 -0
- foundry_mcp/core/research/workflows/__init__.py +25 -0
- foundry_mcp/core/research/workflows/base.py +298 -0
- foundry_mcp/core/research/workflows/chat.py +271 -0
- foundry_mcp/core/research/workflows/consensus.py +539 -0
- foundry_mcp/core/research/workflows/deep_research.py +4142 -0
- foundry_mcp/core/research/workflows/ideate.py +682 -0
- foundry_mcp/core/research/workflows/thinkdeep.py +405 -0
- foundry_mcp/core/resilience.py +600 -0
- foundry_mcp/core/responses.py +1624 -0
- foundry_mcp/core/review.py +366 -0
- foundry_mcp/core/security.py +438 -0
- foundry_mcp/core/spec.py +4119 -0
- foundry_mcp/core/task.py +2463 -0
- foundry_mcp/core/testing.py +839 -0
- foundry_mcp/core/validation.py +2357 -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 +177 -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 +300 -0
- foundry_mcp/dashboard/views/__init__.py +12 -0
- foundry_mcp/dashboard/views/errors.py +217 -0
- foundry_mcp/dashboard/views/metrics.py +164 -0
- foundry_mcp/dashboard/views/overview.py +96 -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/intake-schema.json +89 -0
- foundry_mcp/schemas/sdd-spec-schema.json +414 -0
- foundry_mcp/server.py +150 -0
- foundry_mcp/tools/__init__.py +10 -0
- foundry_mcp/tools/unified/__init__.py +92 -0
- foundry_mcp/tools/unified/authoring.py +3620 -0
- foundry_mcp/tools/unified/context_helpers.py +98 -0
- foundry_mcp/tools/unified/documentation_helpers.py +268 -0
- foundry_mcp/tools/unified/environment.py +1341 -0
- foundry_mcp/tools/unified/error.py +479 -0
- foundry_mcp/tools/unified/health.py +225 -0
- foundry_mcp/tools/unified/journal.py +841 -0
- foundry_mcp/tools/unified/lifecycle.py +640 -0
- foundry_mcp/tools/unified/metrics.py +777 -0
- foundry_mcp/tools/unified/plan.py +876 -0
- foundry_mcp/tools/unified/pr.py +294 -0
- foundry_mcp/tools/unified/provider.py +589 -0
- foundry_mcp/tools/unified/research.py +1283 -0
- foundry_mcp/tools/unified/review.py +1042 -0
- foundry_mcp/tools/unified/review_helpers.py +314 -0
- foundry_mcp/tools/unified/router.py +102 -0
- foundry_mcp/tools/unified/server.py +565 -0
- foundry_mcp/tools/unified/spec.py +1283 -0
- foundry_mcp/tools/unified/task.py +3846 -0
- foundry_mcp/tools/unified/test.py +431 -0
- foundry_mcp/tools/unified/verification.py +520 -0
- foundry_mcp-0.8.22.dist-info/METADATA +344 -0
- foundry_mcp-0.8.22.dist-info/RECORD +153 -0
- foundry_mcp-0.8.22.dist-info/WHEEL +4 -0
- foundry_mcp-0.8.22.dist-info/entry_points.txt +3 -0
- foundry_mcp-0.8.22.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Fixture-backed provider used for offline verification.
|
|
2
|
+
|
|
3
|
+
This provider is intentionally *disabled by default* and only becomes available
|
|
4
|
+
when explicitly enabled via environment variables. It exists to support:
|
|
5
|
+
|
|
6
|
+
- deterministic unit/integration tests
|
|
7
|
+
- offline generation of fidelity/plan review artifacts for SDD specs
|
|
8
|
+
|
|
9
|
+
Security notes:
|
|
10
|
+
- No network access
|
|
11
|
+
- No shell execution
|
|
12
|
+
- Reads only from a configured fixture directory
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
import time
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Any, Dict, Optional
|
|
22
|
+
|
|
23
|
+
from foundry_mcp.core.providers.base import (
|
|
24
|
+
ModelDescriptor,
|
|
25
|
+
ProviderCapability,
|
|
26
|
+
ProviderContext,
|
|
27
|
+
ProviderHooks,
|
|
28
|
+
ProviderMetadata,
|
|
29
|
+
ProviderRequest,
|
|
30
|
+
ProviderResult,
|
|
31
|
+
ProviderStatus,
|
|
32
|
+
TokenUsage,
|
|
33
|
+
)
|
|
34
|
+
from foundry_mcp.core.providers.registry import register_provider
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
_PROVIDER_ID = "test-provider"
|
|
38
|
+
_ENABLE_ENV = "FOUNDRY_TEST_PROVIDER_ENABLED"
|
|
39
|
+
_FIXTURES_DIR_ENV = "FOUNDRY_TEST_PROVIDER_FIXTURES_DIR"
|
|
40
|
+
_DEFAULT_FIXTURES_DIR = Path("tests/fixtures/ai_responses")
|
|
41
|
+
|
|
42
|
+
_WORKFLOW_TO_DEFAULT_FILE = {
|
|
43
|
+
"plan_review": "plan_review_response.json",
|
|
44
|
+
"fidelity_review": "fidelity_review_response.json",
|
|
45
|
+
"markdown_plan_review": "plan_review_response.json",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _is_enabled() -> bool:
|
|
50
|
+
value = os.environ.get(_ENABLE_ENV, "").strip().lower()
|
|
51
|
+
return value in {"1", "true", "yes", "on"}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _resolve_fixtures_dir() -> Path:
|
|
55
|
+
override = os.environ.get(_FIXTURES_DIR_ENV)
|
|
56
|
+
if override:
|
|
57
|
+
return Path(override)
|
|
58
|
+
return _DEFAULT_FIXTURES_DIR
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _load_fixture(*, workflow: str) -> Dict[str, Any]:
|
|
62
|
+
fixtures_dir = _resolve_fixtures_dir()
|
|
63
|
+
filename = _WORKFLOW_TO_DEFAULT_FILE.get(workflow)
|
|
64
|
+
if not filename:
|
|
65
|
+
raise FileNotFoundError(f"No fixture mapping for workflow '{workflow}'")
|
|
66
|
+
|
|
67
|
+
fixture_path = fixtures_dir / filename
|
|
68
|
+
if not fixture_path.exists():
|
|
69
|
+
raise FileNotFoundError(f"Fixture file not found: {fixture_path}")
|
|
70
|
+
|
|
71
|
+
return json.loads(fixture_path.read_text(encoding="utf-8"))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
_TEST_PROVIDER_MODELS = [
|
|
75
|
+
ModelDescriptor(
|
|
76
|
+
id="fixture",
|
|
77
|
+
display_name="Fixture Provider (offline)",
|
|
78
|
+
capabilities={ProviderCapability.TEXT},
|
|
79
|
+
routing_hints={"offline": True, "fixtures": True},
|
|
80
|
+
)
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
_TEST_PROVIDER_METADATA = ProviderMetadata(
|
|
84
|
+
provider_id=_PROVIDER_ID,
|
|
85
|
+
display_name="Test Fixture Provider",
|
|
86
|
+
models=_TEST_PROVIDER_MODELS,
|
|
87
|
+
default_model="fixture",
|
|
88
|
+
capabilities={ProviderCapability.TEXT},
|
|
89
|
+
security_flags={"writes_allowed": False, "read_only": True, "offline": True},
|
|
90
|
+
extra={
|
|
91
|
+
"enabled_env": _ENABLE_ENV,
|
|
92
|
+
"fixtures_dir_env": _FIXTURES_DIR_ENV,
|
|
93
|
+
"default_fixtures_dir": str(_DEFAULT_FIXTURES_DIR),
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class TestFixtureProvider(ProviderContext):
|
|
99
|
+
"""ProviderContext that returns canned responses from fixtures."""
|
|
100
|
+
|
|
101
|
+
def __init__(
|
|
102
|
+
self,
|
|
103
|
+
metadata: ProviderMetadata,
|
|
104
|
+
hooks: Optional[ProviderHooks] = None,
|
|
105
|
+
*,
|
|
106
|
+
model: Optional[str] = None,
|
|
107
|
+
):
|
|
108
|
+
super().__init__(metadata, hooks)
|
|
109
|
+
self._model = model or metadata.default_model or "fixture"
|
|
110
|
+
|
|
111
|
+
def _execute(self, request: ProviderRequest) -> ProviderResult:
|
|
112
|
+
start_time = time.perf_counter()
|
|
113
|
+
|
|
114
|
+
workflow = None
|
|
115
|
+
if isinstance(request.metadata, dict):
|
|
116
|
+
workflow = request.metadata.get("workflow")
|
|
117
|
+
|
|
118
|
+
if not isinstance(workflow, str) or not workflow:
|
|
119
|
+
workflow = "plan_review"
|
|
120
|
+
|
|
121
|
+
fixture = _load_fixture(workflow=workflow)
|
|
122
|
+
tokens = fixture.get("tokens", {}) if isinstance(fixture, dict) else {}
|
|
123
|
+
|
|
124
|
+
duration_ms = (time.perf_counter() - start_time) * 1000
|
|
125
|
+
|
|
126
|
+
return ProviderResult(
|
|
127
|
+
content=str(fixture.get("content", "")),
|
|
128
|
+
provider_id=self._metadata.provider_id,
|
|
129
|
+
model_used=str(fixture.get("model", self._model)),
|
|
130
|
+
status=ProviderStatus.SUCCESS,
|
|
131
|
+
tokens=TokenUsage(
|
|
132
|
+
input_tokens=int(tokens.get("prompt", 0) or 0),
|
|
133
|
+
output_tokens=int(tokens.get("completion", 0) or 0),
|
|
134
|
+
total_tokens=int(tokens.get("total", 0) or 0),
|
|
135
|
+
),
|
|
136
|
+
duration_ms=round(duration_ms, 2),
|
|
137
|
+
raw_payload={
|
|
138
|
+
"fixture_version": fixture.get("fixture_version"),
|
|
139
|
+
"workflow": fixture.get("workflow"),
|
|
140
|
+
"prompt_id": fixture.get("prompt_id"),
|
|
141
|
+
"cached": fixture.get("cached"),
|
|
142
|
+
"timestamp": fixture.get("timestamp"),
|
|
143
|
+
},
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _factory(
|
|
148
|
+
*,
|
|
149
|
+
hooks: ProviderHooks,
|
|
150
|
+
model: Optional[str] = None,
|
|
151
|
+
dependencies: Optional[Dict[str, object]] = None,
|
|
152
|
+
overrides: Optional[Dict[str, object]] = None,
|
|
153
|
+
) -> ProviderContext:
|
|
154
|
+
return TestFixtureProvider(_TEST_PROVIDER_METADATA, hooks, model=model)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _availability_check() -> bool:
|
|
158
|
+
if not _is_enabled():
|
|
159
|
+
return False
|
|
160
|
+
return _resolve_fixtures_dir().exists()
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
register_provider(
|
|
164
|
+
_PROVIDER_ID,
|
|
165
|
+
factory=_factory,
|
|
166
|
+
metadata=_TEST_PROVIDER_METADATA,
|
|
167
|
+
availability_check=_availability_check,
|
|
168
|
+
priority=0,
|
|
169
|
+
description="Offline fixture-backed provider (tests/verification only)",
|
|
170
|
+
tags=("test", "offline"),
|
|
171
|
+
)
|