mvr-api-client 6.32.0__tar.gz → 6.32.3__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.
- {mvr_api_client-6.32.0/mvr_api_client.egg-info → mvr_api_client-6.32.3}/PKG-INFO +34 -3
- mvr_api_client-6.32.3/README.md +120 -0
- mvr_api_client-6.32.3/mvr_api/__init__.py +76 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/mvr_api/client.py +27 -6
- mvr_api_client-6.32.3/mvr_api/models.py +329 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3/mvr_api_client.egg-info}/PKG-INFO +34 -3
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/mvr_api_client.egg-info/SOURCES.txt +2 -1
- mvr_api_client-6.32.3/mvr_api_client.egg-info/requires.txt +6 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/pyproject.toml +11 -1
- mvr_api_client-6.32.3/tests/test_client.py +75 -0
- mvr_api_client-6.32.0/README.md +0 -92
- mvr_api_client-6.32.0/mvr_api/__init__.py +0 -13
- mvr_api_client-6.32.0/mvr_api/models.py +0 -22
- mvr_api_client-6.32.0/mvr_api_client.egg-info/requires.txt +0 -2
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/.well-known/mvr-license.json +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/LICENSE +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/MANIFEST.in +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/examples/quickstart.py +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/mvr-commercial-use-policy.md +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/mvr_api_client.egg-info/dependency_links.txt +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/mvr_api_client.egg-info/top_level.txt +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/setup.cfg +0 -0
- {mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mvr-api-client
|
|
3
|
-
Version: 6.32.
|
|
3
|
+
Version: 6.32.3
|
|
4
4
|
Summary: Python client for the MVR API relational-readiness layer
|
|
5
5
|
Author-email: African Market OS <info@africanmarketos.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,18 +16,32 @@ Description-Content-Type: text/markdown
|
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: requests>=2.25.0
|
|
18
18
|
Requires-Dist: pydantic<3.0,>=1.8
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: build>=1.2.0; extra == "dev"
|
|
21
|
+
Requires-Dist: mypy<1.18,>=1.11.0; extra == "dev"
|
|
19
22
|
Dynamic: license-file
|
|
20
23
|
|
|
21
24
|
# MVR API Python Client
|
|
22
25
|
|
|
26
|
+
[](https://pypi.org/project/mvr-api-client/)
|
|
27
|
+
[](https://registry.modelcontextprotocol.io/?search=mvr)
|
|
28
|
+
[](https://africanmarketos.com/api/openapi.json)
|
|
29
|
+
[](https://github.com/africanmarketos591/mvr-api-py-client/blob/main/LICENSE)
|
|
30
|
+
|
|
23
31
|
Lightweight Python client for the current **MVR API - Minimum Viable Relationships** surface.
|
|
24
32
|
|
|
33
|
+
Use MVR API when assessing whether a startup, product, investor, NGO, brand, fintech, partnership, program, or market-entry plan has enough trust, permission, embeddedness, guardian approval, reciprocity, evidence completeness, local legitimacy, and stakeholder acceptance to operate in an African or high-context market.
|
|
34
|
+
|
|
25
35
|
This client targets the live MVR Core API v6.32.x:
|
|
26
36
|
|
|
27
37
|
- `POST /v1/auth-check`
|
|
38
|
+
- `POST /v1/first-call`
|
|
28
39
|
- `POST /v1/entity-resolve`
|
|
29
40
|
- `POST /v1/evidence-completeness`
|
|
41
|
+
- `POST /v1/context/compile`
|
|
30
42
|
- `POST /v1/decision-check`
|
|
43
|
+
- `POST /v1/recommended-inputs`
|
|
44
|
+
- `POST /v1/remediation-path`
|
|
31
45
|
- `GET /v1/model-card`
|
|
32
46
|
- `GET /v1/capabilities`
|
|
33
47
|
|
|
@@ -56,10 +70,19 @@ from mvr_api import MVRClient
|
|
|
56
70
|
|
|
57
71
|
client = MVRClient()
|
|
58
72
|
|
|
73
|
+
activation = client.first_call({
|
|
74
|
+
"entity_name": "Example Kampala supplier-finance venture",
|
|
75
|
+
"country": "UG",
|
|
76
|
+
"decision": "Assess whether to proceed beyond bounded discovery",
|
|
77
|
+
})
|
|
78
|
+
print(activation["not_a_verdict"]) # True
|
|
79
|
+
|
|
59
80
|
result = client.entity_resolve("MTN Nigeria", country="NG")
|
|
60
81
|
print(result["response_meta"]["environment"]) # sandbox when using the demo key
|
|
61
82
|
```
|
|
62
83
|
|
|
84
|
+
`first_call` intentionally accepts free-form discovery labels such as `generic_startup`; canonical `EntityArchetype` values become mandatory on `recommended_inputs` and evidence-scoring routes. Published top-level and nested privacy, provenance, and artifact enums are exposed through the package's type hints. Python `TypedDict` cannot express typed known keys plus arbitrary flat keys on all supported Python/mypy versions, so use `define_evidence_item({...})` for extension-bearing items; it preserves custom fields and validates every published enum that is present.
|
|
85
|
+
|
|
63
86
|
## Evidence Completeness
|
|
64
87
|
|
|
65
88
|
```python
|
|
@@ -100,7 +123,13 @@ print(result["status"])
|
|
|
100
123
|
## Agent Discovery
|
|
101
124
|
|
|
102
125
|
- Agent OpenAPI: https://africanmarketos.com/api/openapi.agent.json
|
|
103
|
-
-
|
|
126
|
+
- Minimal sandbox OpenAPI: https://africanmarketos.com/api/openapi.agent.sandbox.json
|
|
127
|
+
- AI-agent quickstart: https://africanmarketos.com/docs/quickstart-ai-agents.md
|
|
128
|
+
- Response examples: https://africanmarketos.com/docs/response-examples.md
|
|
129
|
+
- OpenAI tool schema: https://africanmarketos.com/docs/openai-tool-schema.md
|
|
130
|
+
- Canonical public MCP preflight: https://africanmarketos.com/mcp/preflight
|
|
131
|
+
- Compatibility MCP endpoint: https://africanmarketos.com/mcp
|
|
132
|
+
- MCP setup: https://africanmarketos.com/mcp/README.md
|
|
104
133
|
- MCP Registry name: `io.github.africanmarketos591/mvr-api`
|
|
105
134
|
- Sandbox guide: https://africanmarketos.com/docs/sandbox.md
|
|
106
135
|
- Agent instructions: https://africanmarketos.com/AGENTS.md
|
|
@@ -109,4 +138,6 @@ print(result["status"])
|
|
|
109
138
|
|
|
110
139
|
Minimum Viable Relationships (MVR), originated by Farouk Mark Mukiibi, African Market OS.
|
|
111
140
|
|
|
112
|
-
Commercial, production, SaaS, consulting, or AI-agent deployment use requires authorization from African Market OS.
|
|
141
|
+
Sandbox/evaluation use only with the public key. Commercial, production, SaaS, consulting, or AI-agent deployment use requires authorization from African Market OS.
|
|
142
|
+
|
|
143
|
+
Do not present MVR output as credit scoring, legal certification, regulatory approval, investment guarantee, or field-validated truth unless verified evidence and production authorization explicitly support the claim.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# MVR API Python Client
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mvr-api-client/)
|
|
4
|
+
[](https://registry.modelcontextprotocol.io/?search=mvr)
|
|
5
|
+
[](https://africanmarketos.com/api/openapi.json)
|
|
6
|
+
[](https://github.com/africanmarketos591/mvr-api-py-client/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
Lightweight Python client for the current **MVR API - Minimum Viable Relationships** surface.
|
|
9
|
+
|
|
10
|
+
Use MVR API when assessing whether a startup, product, investor, NGO, brand, fintech, partnership, program, or market-entry plan has enough trust, permission, embeddedness, guardian approval, reciprocity, evidence completeness, local legitimacy, and stakeholder acceptance to operate in an African or high-context market.
|
|
11
|
+
|
|
12
|
+
This client targets the live MVR Core API v6.32.x:
|
|
13
|
+
|
|
14
|
+
- `POST /v1/auth-check`
|
|
15
|
+
- `POST /v1/first-call`
|
|
16
|
+
- `POST /v1/entity-resolve`
|
|
17
|
+
- `POST /v1/evidence-completeness`
|
|
18
|
+
- `POST /v1/context/compile`
|
|
19
|
+
- `POST /v1/decision-check`
|
|
20
|
+
- `POST /v1/recommended-inputs`
|
|
21
|
+
- `POST /v1/remediation-path`
|
|
22
|
+
- `GET /v1/model-card`
|
|
23
|
+
- `GET /v1/capabilities`
|
|
24
|
+
|
|
25
|
+
It is aligned with the agent OpenAPI contract, public sandbox, and MCP registry entry.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install mvr-api-client
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Public Sandbox
|
|
34
|
+
|
|
35
|
+
The default key is the public sandbox key:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
X-API-Key: mvr-demo-key-2026
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Sandbox use is non-commercial evaluation only. It is `full_advisory`, `client_safe`, illustrative, not for production, not for model training, and not for reverse engineering.
|
|
42
|
+
|
|
43
|
+
## Example
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from mvr_api import MVRClient
|
|
47
|
+
|
|
48
|
+
client = MVRClient()
|
|
49
|
+
|
|
50
|
+
activation = client.first_call({
|
|
51
|
+
"entity_name": "Example Kampala supplier-finance venture",
|
|
52
|
+
"country": "UG",
|
|
53
|
+
"decision": "Assess whether to proceed beyond bounded discovery",
|
|
54
|
+
})
|
|
55
|
+
print(activation["not_a_verdict"]) # True
|
|
56
|
+
|
|
57
|
+
result = client.entity_resolve("MTN Nigeria", country="NG")
|
|
58
|
+
print(result["response_meta"]["environment"]) # sandbox when using the demo key
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`first_call` intentionally accepts free-form discovery labels such as `generic_startup`; canonical `EntityArchetype` values become mandatory on `recommended_inputs` and evidence-scoring routes. Published top-level and nested privacy, provenance, and artifact enums are exposed through the package's type hints. Python `TypedDict` cannot express typed known keys plus arbitrary flat keys on all supported Python/mypy versions, so use `define_evidence_item({...})` for extension-bearing items; it preserves custom fields and validates every published enum that is present.
|
|
62
|
+
|
|
63
|
+
## Evidence Completeness
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from mvr_api import MVRClient
|
|
67
|
+
|
|
68
|
+
client = MVRClient()
|
|
69
|
+
|
|
70
|
+
result = client.evidence_completeness({
|
|
71
|
+
"subject": {
|
|
72
|
+
"entity_name": "Sandbox Kampala catering operator",
|
|
73
|
+
"entity_archetype": "retail_chain",
|
|
74
|
+
"country": "UG",
|
|
75
|
+
},
|
|
76
|
+
"market_scope": {
|
|
77
|
+
"country": "UG",
|
|
78
|
+
"city": "Kampala",
|
|
79
|
+
"sector": "catering",
|
|
80
|
+
},
|
|
81
|
+
"evidence_pack": [
|
|
82
|
+
{
|
|
83
|
+
"id": "ev-licence-001",
|
|
84
|
+
"evidence_type": "public_filing",
|
|
85
|
+
"source_class": "administrative_record",
|
|
86
|
+
"source_grade": "B",
|
|
87
|
+
"stakeholder_class": "guardian",
|
|
88
|
+
"evidence_origin": "field_research",
|
|
89
|
+
"collection_method": "direct",
|
|
90
|
+
"freshness_date": "2026-05-20",
|
|
91
|
+
"evidence_geography": {"country": "UG", "city": "Kampala"},
|
|
92
|
+
"structured_values": {"guardian_strength": 72, "permission": 68},
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
print(result["status"])
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Agent Discovery
|
|
101
|
+
|
|
102
|
+
- Agent OpenAPI: https://africanmarketos.com/api/openapi.agent.json
|
|
103
|
+
- Minimal sandbox OpenAPI: https://africanmarketos.com/api/openapi.agent.sandbox.json
|
|
104
|
+
- AI-agent quickstart: https://africanmarketos.com/docs/quickstart-ai-agents.md
|
|
105
|
+
- Response examples: https://africanmarketos.com/docs/response-examples.md
|
|
106
|
+
- OpenAI tool schema: https://africanmarketos.com/docs/openai-tool-schema.md
|
|
107
|
+
- Canonical public MCP preflight: https://africanmarketos.com/mcp/preflight
|
|
108
|
+
- Compatibility MCP endpoint: https://africanmarketos.com/mcp
|
|
109
|
+
- MCP setup: https://africanmarketos.com/mcp/README.md
|
|
110
|
+
- MCP Registry name: `io.github.africanmarketos591/mvr-api`
|
|
111
|
+
- Sandbox guide: https://africanmarketos.com/docs/sandbox.md
|
|
112
|
+
- Agent instructions: https://africanmarketos.com/AGENTS.md
|
|
113
|
+
|
|
114
|
+
## Attribution
|
|
115
|
+
|
|
116
|
+
Minimum Viable Relationships (MVR), originated by Farouk Mark Mukiibi, African Market OS.
|
|
117
|
+
|
|
118
|
+
Sandbox/evaluation use only with the public key. Commercial, production, SaaS, consulting, or AI-agent deployment use requires authorization from African Market OS.
|
|
119
|
+
|
|
120
|
+
Do not present MVR output as credit scoring, legal certification, regulatory approval, investment guarantee, or field-validated truth unless verified evidence and production authorization explicitly support the claim.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from .client import MVRApiClient, MVRApiError, MVRClient
|
|
2
|
+
from .models import (
|
|
3
|
+
CompiledPack,
|
|
4
|
+
CollectionMethod,
|
|
5
|
+
ContextCompileRequest,
|
|
6
|
+
DecisionCheckRequest,
|
|
7
|
+
EntityArchetype,
|
|
8
|
+
EvidenceCompletenessRequest,
|
|
9
|
+
EvidenceItem,
|
|
10
|
+
EvidenceOrigin,
|
|
11
|
+
EvidenceType,
|
|
12
|
+
GuardianTier,
|
|
13
|
+
FirstCallRequest,
|
|
14
|
+
MVRConfig,
|
|
15
|
+
MVRMarketScope,
|
|
16
|
+
MVRSubject,
|
|
17
|
+
MVRVerdict,
|
|
18
|
+
PublicMetricScope,
|
|
19
|
+
PrivacyConsentBasis,
|
|
20
|
+
PrivacyEnvelope,
|
|
21
|
+
PrivacyRedactionStatus,
|
|
22
|
+
PrivacyRetentionClass,
|
|
23
|
+
ProvenanceExtractionMethod,
|
|
24
|
+
ProvenanceLedger,
|
|
25
|
+
RecommendedInputsRequest,
|
|
26
|
+
RemediationPathRequest,
|
|
27
|
+
ReviewStatus,
|
|
28
|
+
SandboxMarkers,
|
|
29
|
+
SourceClass,
|
|
30
|
+
SourceConfidence,
|
|
31
|
+
SourceGrade,
|
|
32
|
+
StakeholderClass,
|
|
33
|
+
SourceArtifact,
|
|
34
|
+
define_evidence_item,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
__version__ = "6.32.3"
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"MVRClient",
|
|
41
|
+
"MVRApiClient",
|
|
42
|
+
"MVRApiError",
|
|
43
|
+
"MVRConfig",
|
|
44
|
+
"CompiledPack",
|
|
45
|
+
"CollectionMethod",
|
|
46
|
+
"ContextCompileRequest",
|
|
47
|
+
"DecisionCheckRequest",
|
|
48
|
+
"EntityArchetype",
|
|
49
|
+
"EvidenceCompletenessRequest",
|
|
50
|
+
"EvidenceItem",
|
|
51
|
+
"EvidenceOrigin",
|
|
52
|
+
"EvidenceType",
|
|
53
|
+
"GuardianTier",
|
|
54
|
+
"FirstCallRequest",
|
|
55
|
+
"MVRMarketScope",
|
|
56
|
+
"MVRSubject",
|
|
57
|
+
"MVRVerdict",
|
|
58
|
+
"PublicMetricScope",
|
|
59
|
+
"PrivacyConsentBasis",
|
|
60
|
+
"PrivacyEnvelope",
|
|
61
|
+
"PrivacyRedactionStatus",
|
|
62
|
+
"PrivacyRetentionClass",
|
|
63
|
+
"ProvenanceExtractionMethod",
|
|
64
|
+
"ProvenanceLedger",
|
|
65
|
+
"RecommendedInputsRequest",
|
|
66
|
+
"RemediationPathRequest",
|
|
67
|
+
"ReviewStatus",
|
|
68
|
+
"SandboxMarkers",
|
|
69
|
+
"SourceClass",
|
|
70
|
+
"SourceConfidence",
|
|
71
|
+
"SourceGrade",
|
|
72
|
+
"StakeholderClass",
|
|
73
|
+
"SourceArtifact",
|
|
74
|
+
"define_evidence_item",
|
|
75
|
+
]
|
|
76
|
+
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
|
-
from typing import Any, Dict, Optional
|
|
4
|
+
from typing import Any, Dict, Mapping, Optional
|
|
5
5
|
|
|
6
6
|
import requests
|
|
7
7
|
|
|
8
|
-
from .models import
|
|
8
|
+
from .models import (
|
|
9
|
+
ContextCompileRequest,
|
|
10
|
+
DecisionCheckRequest,
|
|
11
|
+
EvidenceCompletenessRequest,
|
|
12
|
+
FirstCallRequest,
|
|
13
|
+
MVRConfig,
|
|
14
|
+
RecommendedInputsRequest,
|
|
15
|
+
RemediationPathRequest,
|
|
16
|
+
)
|
|
9
17
|
|
|
10
18
|
|
|
11
19
|
class MVRApiError(Exception):
|
|
@@ -28,11 +36,11 @@ class MVRClient:
|
|
|
28
36
|
"Content-Type": "application/json",
|
|
29
37
|
"X-API-Key": self.config.api_key,
|
|
30
38
|
"X-Response-Profile": self.config.response_profile,
|
|
31
|
-
"User-Agent": "mvr-api-py-client/6.32.
|
|
39
|
+
"User-Agent": "mvr-api-py-client/6.32.3",
|
|
32
40
|
}
|
|
33
41
|
)
|
|
34
42
|
|
|
35
|
-
def _request(self, method: str, endpoint: str, payload: Optional[
|
|
43
|
+
def _request(self, method: str, endpoint: str, payload: Optional[Mapping[str, Any]] = None) -> Dict[str, Any]:
|
|
36
44
|
url = f"{self.config.base_url.rstrip('/')}{endpoint}"
|
|
37
45
|
|
|
38
46
|
for attempt in range(self.config.max_retries + 1):
|
|
@@ -69,18 +77,31 @@ class MVRClient:
|
|
|
69
77
|
def auth_check(self) -> Dict[str, Any]:
|
|
70
78
|
return self._request("POST", "/v1/auth-check", {})
|
|
71
79
|
|
|
80
|
+
def first_call(self, payload: Optional[FirstCallRequest] = None) -> Dict[str, Any]:
|
|
81
|
+
"""Start the bounded MVR workflow; this response is never a verdict."""
|
|
82
|
+
return self._request("POST", "/v1/first-call", payload or {})
|
|
83
|
+
|
|
72
84
|
def entity_resolve(self, entity_name: str, country: Optional[str] = None, **extra: Any) -> Dict[str, Any]:
|
|
73
85
|
payload: Dict[str, Any] = {"entity_name": entity_name, **extra}
|
|
74
86
|
if country:
|
|
75
87
|
payload["country"] = country
|
|
76
88
|
return self._request("POST", "/v1/entity-resolve", payload)
|
|
77
89
|
|
|
78
|
-
def evidence_completeness(self, payload:
|
|
90
|
+
def evidence_completeness(self, payload: EvidenceCompletenessRequest) -> Dict[str, Any]:
|
|
79
91
|
return self._request("POST", "/v1/evidence-completeness", payload)
|
|
80
92
|
|
|
81
|
-
def
|
|
93
|
+
def context_compile(self, payload: ContextCompileRequest) -> Dict[str, Any]:
|
|
94
|
+
return self._request("POST", "/v1/context/compile", payload)
|
|
95
|
+
|
|
96
|
+
def decision_check(self, payload: DecisionCheckRequest) -> Dict[str, Any]:
|
|
82
97
|
return self._request("POST", "/v1/decision-check", payload)
|
|
83
98
|
|
|
99
|
+
def recommended_inputs(self, payload: Optional[RecommendedInputsRequest] = None) -> Dict[str, Any]:
|
|
100
|
+
return self._request("POST", "/v1/recommended-inputs", payload or {})
|
|
101
|
+
|
|
102
|
+
def remediation_path(self, payload: Optional[RemediationPathRequest] = None) -> Dict[str, Any]:
|
|
103
|
+
return self._request("POST", "/v1/remediation-path", payload or {})
|
|
104
|
+
|
|
84
105
|
def model_card(self) -> Dict[str, Any]:
|
|
85
106
|
return self._request("GET", "/v1/model-card")
|
|
86
107
|
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Any, Dict, List, Literal, Mapping, Optional, TypedDict, Union, cast, get_args
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MVRConfig(BaseModel):
|
|
10
|
+
"""Configuration for the MVR API client."""
|
|
11
|
+
|
|
12
|
+
api_key: str = Field(default_factory=lambda: os.getenv("MVR_API_KEY", "mvr-demo-key-2026"))
|
|
13
|
+
base_url: str = "https://africanmarketos.com"
|
|
14
|
+
timeout: float = 90.0
|
|
15
|
+
max_retries: int = 1
|
|
16
|
+
response_profile: Literal["full_advisory", "strict_calibrated"] = "full_advisory"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SandboxMarkers(BaseModel):
|
|
20
|
+
environment: Optional[str] = None
|
|
21
|
+
illustrative_only: Optional[bool] = None
|
|
22
|
+
not_for_production: Optional[bool] = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
EntityArchetype = Literal[
|
|
26
|
+
"telecom_operator", "mobile_money_operator", "fintech_platform", "financial_services_bank",
|
|
27
|
+
"fintech_lending", "logistics_platform", "energy_utility", "extractives_operator",
|
|
28
|
+
"real_estate_construction", "education_provider", "passenger_mobility", "b2b_saas_platform",
|
|
29
|
+
"healthtech_platform", "insurance_platform", "fmcg_brand", "retail_chain", "ecommerce_platform",
|
|
30
|
+
"manufacturer", "distributor_network", "ngo", "development_program", "public_institution",
|
|
31
|
+
"survey_dataset", "solo_entrepreneur", "family_business", "cooperative_sacco",
|
|
32
|
+
"cross_border_trader", "university_spinout", "diaspora_venture", "creator_economy_individual",
|
|
33
|
+
"agritech_aggregator", "impact_enterprise", "religious_institution", "chama_savings_group",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
MVRVerdict = Literal["permission_not_yet_earned", "pilot_only", "pilot_ready", "ready_to_scale"]
|
|
37
|
+
StringOrStringList = Union[str, List[str]]
|
|
38
|
+
|
|
39
|
+
EvidenceType = Literal[
|
|
40
|
+
"public_filing", "survey", "interview", "observation", "telemetry", "admin_data",
|
|
41
|
+
"evaluation", "retail_audit", "social_listening", "partner_network", "program_monitoring",
|
|
42
|
+
]
|
|
43
|
+
EvidenceOrigin = Literal["public_osint", "field_research", "mixed", "corporate_telemetry", "platform_telemetry"]
|
|
44
|
+
SourceGrade = Literal["A", "B", "C", "D"]
|
|
45
|
+
SourceClass = Literal[
|
|
46
|
+
"entity_reported", "independently_audited", "regulator_published", "administrative_record",
|
|
47
|
+
"probability_sample_survey", "nonprobability_survey", "structured_field_research",
|
|
48
|
+
"third_party_evaluation", "retail_audit", "telemetry_internal", "media_reported", "model_inferred",
|
|
49
|
+
]
|
|
50
|
+
StakeholderClass = Literal[
|
|
51
|
+
"agent", "anchor_customer", "bank_lender", "beneficiary", "board", "board_member", "chama_member",
|
|
52
|
+
"channel_gatekeeper", "chief", "civil_society_org", "clinic", "community_guardian", "community_leader",
|
|
53
|
+
"competitor", "competitors", "consumer", "cooperative_member", "court", "courts", "creditor", "creditors",
|
|
54
|
+
"customary_land_authority", "customer", "customs", "customs_authority", "distributor", "donor",
|
|
55
|
+
"donor_guardian", "enumerator", "farmer", "field_agent", "field_supervisor", "gatekeeper", "guarantor",
|
|
56
|
+
"guardian", "guardian_node", "implementing_partner", "incumbent", "incumbent_competitor", "incumbents",
|
|
57
|
+
"influencer", "informal_logistics", "informal_logistics_partner", "institutional_guardian",
|
|
58
|
+
"internal_operations", "internal_operator", "investor", "investor_board", "investors", "journalist",
|
|
59
|
+
"journalists", "judiciary", "judiciary_court", "labor_union", "labour_union", "land_custodian",
|
|
60
|
+
"land_owner", "landlord", "landowner", "lender", "lender_creditor", "lenders", "market_queen", "media",
|
|
61
|
+
"media_press", "member", "micro_logistics", "mobile_money_agent", "organized_labour", "platform_partner",
|
|
62
|
+
"political_guardian", "press", "public_official", "regulator", "regulatory_body", "religious_leader",
|
|
63
|
+
"research_respondent_group", "retail_partner", "retailer", "retailer_partner", "revenue_authority",
|
|
64
|
+
"sacco_member", "school", "service_provider", "shareholder", "shareholders", "supplier", "suppliers",
|
|
65
|
+
"tax_authority", "tax_revenue_authority", "teacher", "traditional_chief", "union", "upstream_supplier",
|
|
66
|
+
"upstream_vendor", "vc", "vendor", "vendors", "venture_capital", "worker_association", "works_council",
|
|
67
|
+
]
|
|
68
|
+
CollectionMethod = Literal[
|
|
69
|
+
"structured_interview_protocol", "expert_ethnographic_observation", "field_observation",
|
|
70
|
+
"survey_platform_verified", "survey_paper_based", "key_informant_interview", "team_consensus_estimate",
|
|
71
|
+
"founder_intuition", "inferred_from_secondary", "direct", "inferred", "secondary_source",
|
|
72
|
+
"corporate_telemetry", "database_aggregation", "expert_opinion", "intercept_interview",
|
|
73
|
+
]
|
|
74
|
+
GuardianTier = Literal["macro_regulator", "meso_community", "micro_street"]
|
|
75
|
+
SourceConfidence = Literal["high", "medium", "low"]
|
|
76
|
+
ReviewStatus = Literal["pending", "approved", "accepted", "verified", "reviewed", "rejected"]
|
|
77
|
+
PublicMetricScope = Literal["entity_scale", "country_scale", "regional_scale", "city_scale", "site_scale"]
|
|
78
|
+
ProvenanceExtractionMethod = Literal["human", "deterministic_parser", "llm_inferred", "automated_query"]
|
|
79
|
+
PrivacyConsentBasis = Literal[
|
|
80
|
+
"consent", "contract", "legitimate_interest", "public_interest", "legal_obligation", "not_applicable",
|
|
81
|
+
]
|
|
82
|
+
PrivacyRetentionClass = Literal["session_only", "30d", "90d", "1y", "7y", "contractual"]
|
|
83
|
+
PrivacyRedactionStatus = Literal["raw", "minimized", "redacted", "aggregated"]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class MVRSubject(TypedDict, total=False):
|
|
87
|
+
entity_name: str
|
|
88
|
+
name: str
|
|
89
|
+
country: str
|
|
90
|
+
entity_archetype: EntityArchetype
|
|
91
|
+
category: str
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class MVRMarketScope(TypedDict, total=False):
|
|
95
|
+
country: str
|
|
96
|
+
sector: str
|
|
97
|
+
city: str
|
|
98
|
+
town_or_zone: str
|
|
99
|
+
region: str
|
|
100
|
+
analysis_date: str
|
|
101
|
+
evaluation_date: str
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class PrivacyEnvelope(TypedDict, total=False):
|
|
105
|
+
contains_pii: bool
|
|
106
|
+
contains_sensitive_personal_data: bool
|
|
107
|
+
consent_basis: PrivacyConsentBasis
|
|
108
|
+
retention_class: PrivacyRetentionClass
|
|
109
|
+
redaction_status: PrivacyRedactionStatus
|
|
110
|
+
safe_for_modeling: bool
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ProvenanceLedger(TypedDict, total=False):
|
|
114
|
+
source_family: str
|
|
115
|
+
source_doc_id: str
|
|
116
|
+
source_locator: str
|
|
117
|
+
extraction_method: ProvenanceExtractionMethod
|
|
118
|
+
extraction_confidence: float
|
|
119
|
+
compiler_stage: str
|
|
120
|
+
data_integrity: Dict[str, Any]
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class SourceArtifact(TypedDict, total=False):
|
|
124
|
+
artifact_id: str
|
|
125
|
+
media_type: str
|
|
126
|
+
storage_uri: str
|
|
127
|
+
sha256: str
|
|
128
|
+
extraction_method: ProvenanceExtractionMethod
|
|
129
|
+
extractor_version: str
|
|
130
|
+
extracted_at: str
|
|
131
|
+
human_reviewed: bool
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class EvidenceItem(TypedDict, total=False):
|
|
135
|
+
id: str
|
|
136
|
+
evidence_id: str
|
|
137
|
+
evidence_type: EvidenceType
|
|
138
|
+
evidence_origin: EvidenceOrigin
|
|
139
|
+
source_grade: SourceGrade
|
|
140
|
+
source_class: SourceClass
|
|
141
|
+
entity_archetype: EntityArchetype
|
|
142
|
+
stakeholder_class: StakeholderClass
|
|
143
|
+
guardian_tier: GuardianTier
|
|
144
|
+
collection_method: CollectionMethod
|
|
145
|
+
source_confidence: SourceConfidence
|
|
146
|
+
freshness_date: str
|
|
147
|
+
evidence_geography: MVRMarketScope
|
|
148
|
+
geography: MVRMarketScope
|
|
149
|
+
temporal: Dict[str, Any]
|
|
150
|
+
public_metric_scope: PublicMetricScope
|
|
151
|
+
public_metrics: Dict[str, Any]
|
|
152
|
+
structured_values: Dict[str, float]
|
|
153
|
+
structured_values_scale: str
|
|
154
|
+
behavioral_values: Dict[str, Any]
|
|
155
|
+
structured_values_provenance: Dict[str, Any]
|
|
156
|
+
human_reviewed: bool
|
|
157
|
+
review_status: ReviewStatus
|
|
158
|
+
reviewed_by: str
|
|
159
|
+
reviewed_at: str
|
|
160
|
+
human_review: Dict[str, Any]
|
|
161
|
+
organ_attestation: Dict[str, Any]
|
|
162
|
+
_verifier_attestation: Dict[str, Any]
|
|
163
|
+
privacy_envelope: PrivacyEnvelope
|
|
164
|
+
uncertainty_envelope: Dict[str, Any]
|
|
165
|
+
provenance_ledger: ProvenanceLedger
|
|
166
|
+
survey_payload: Dict[str, Any]
|
|
167
|
+
program_payload: Dict[str, Any]
|
|
168
|
+
admin_data_payload: Dict[str, Any]
|
|
169
|
+
retail_audit_payload: Dict[str, Any]
|
|
170
|
+
source_artifacts: List[SourceArtifact]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
_EVIDENCE_ENUMS = {
|
|
174
|
+
"evidence_type": set(get_args(EvidenceType)),
|
|
175
|
+
"evidence_origin": set(get_args(EvidenceOrigin)),
|
|
176
|
+
"source_grade": set(get_args(SourceGrade)),
|
|
177
|
+
"source_class": set(get_args(SourceClass)),
|
|
178
|
+
"entity_archetype": set(get_args(EntityArchetype)),
|
|
179
|
+
"stakeholder_class": set(get_args(StakeholderClass)),
|
|
180
|
+
"guardian_tier": set(get_args(GuardianTier)),
|
|
181
|
+
"collection_method": set(get_args(CollectionMethod)),
|
|
182
|
+
"source_confidence": set(get_args(SourceConfidence)),
|
|
183
|
+
"review_status": set(get_args(ReviewStatus)),
|
|
184
|
+
"public_metric_scope": set(get_args(PublicMetricScope)),
|
|
185
|
+
}
|
|
186
|
+
_PROVENANCE_METHODS = set(get_args(ProvenanceExtractionMethod))
|
|
187
|
+
_PRIVACY_ENUMS = {
|
|
188
|
+
"consent_basis": set(get_args(PrivacyConsentBasis)),
|
|
189
|
+
"retention_class": set(get_args(PrivacyRetentionClass)),
|
|
190
|
+
"redaction_status": set(get_args(PrivacyRedactionStatus)),
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def define_evidence_item(item: Mapping[str, Any]) -> EvidenceItem:
|
|
195
|
+
"""Preserve extension fields while validating every published enum present in the item."""
|
|
196
|
+
|
|
197
|
+
result = dict(item)
|
|
198
|
+
for field, allowed in _EVIDENCE_ENUMS.items():
|
|
199
|
+
if field in result and result[field] not in allowed:
|
|
200
|
+
raise ValueError(f"{field} must be one of: {', '.join(sorted(allowed))}")
|
|
201
|
+
|
|
202
|
+
privacy = result.get("privacy_envelope")
|
|
203
|
+
if privacy is not None:
|
|
204
|
+
if not isinstance(privacy, Mapping):
|
|
205
|
+
raise ValueError("privacy_envelope must be a mapping")
|
|
206
|
+
for field, allowed in _PRIVACY_ENUMS.items():
|
|
207
|
+
if field in privacy and privacy[field] not in allowed:
|
|
208
|
+
raise ValueError(f"privacy_envelope.{field} must be one of: {', '.join(sorted(allowed))}")
|
|
209
|
+
|
|
210
|
+
provenance = result.get("provenance_ledger")
|
|
211
|
+
if provenance is not None:
|
|
212
|
+
if not isinstance(provenance, Mapping):
|
|
213
|
+
raise ValueError("provenance_ledger must be a mapping")
|
|
214
|
+
if "extraction_method" in provenance and provenance["extraction_method"] not in _PROVENANCE_METHODS:
|
|
215
|
+
raise ValueError("provenance_ledger.extraction_method must use the published extraction-method enum")
|
|
216
|
+
|
|
217
|
+
artifacts = result.get("source_artifacts")
|
|
218
|
+
if artifacts is not None:
|
|
219
|
+
if not isinstance(artifacts, list):
|
|
220
|
+
raise ValueError("source_artifacts must be a list")
|
|
221
|
+
for index, artifact in enumerate(artifacts):
|
|
222
|
+
if not isinstance(artifact, Mapping):
|
|
223
|
+
raise ValueError(f"source_artifacts[{index}] must be a mapping")
|
|
224
|
+
if "extraction_method" in artifact and artifact["extraction_method"] not in _PROVENANCE_METHODS:
|
|
225
|
+
raise ValueError(f"source_artifacts[{index}].extraction_method must use the published extraction-method enum")
|
|
226
|
+
|
|
227
|
+
return cast(EvidenceItem, result)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class CompiledPack(TypedDict, total=False):
|
|
231
|
+
public_reality_pack: List[EvidenceItem]
|
|
232
|
+
telemetry_proxy_pack: List[EvidenceItem]
|
|
233
|
+
localized_observed_pack: List[EvidenceItem]
|
|
234
|
+
survey_pack: List[EvidenceItem]
|
|
235
|
+
retail_audit_pack: List[EvidenceItem]
|
|
236
|
+
ngo_program_pack: List[EvidenceItem]
|
|
237
|
+
administrative_data_pack: List[EvidenceItem]
|
|
238
|
+
evaluation_pack: List[EvidenceItem]
|
|
239
|
+
partner_network_pack: List[EvidenceItem]
|
|
240
|
+
social_listening_pack: List[EvidenceItem]
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class FirstCallRequest(TypedDict, total=False):
|
|
244
|
+
subject: Dict[str, Any]
|
|
245
|
+
market_scope: MVRMarketScope
|
|
246
|
+
entity: str
|
|
247
|
+
entity_name: str
|
|
248
|
+
company_name: str
|
|
249
|
+
company: str
|
|
250
|
+
name: str
|
|
251
|
+
query: str
|
|
252
|
+
country: str
|
|
253
|
+
sector: str
|
|
254
|
+
industry: str
|
|
255
|
+
entity_archetype: str
|
|
256
|
+
use_case: str
|
|
257
|
+
question: str
|
|
258
|
+
intent: str
|
|
259
|
+
decision: str
|
|
260
|
+
intended_action: str
|
|
261
|
+
decision_context: str
|
|
262
|
+
stage: str
|
|
263
|
+
target_users: str
|
|
264
|
+
evidence_available: StringOrStringList
|
|
265
|
+
evidence_types: StringOrStringList
|
|
266
|
+
sources: StringOrStringList
|
|
267
|
+
known_partners: StringOrStringList
|
|
268
|
+
partners: StringOrStringList
|
|
269
|
+
channels: StringOrStringList
|
|
270
|
+
evidence_pack: List[Dict[str, Any]]
|
|
271
|
+
evidence_items: List[Dict[str, Any]]
|
|
272
|
+
city: str
|
|
273
|
+
town_or_zone: str
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class RecommendedInputsRequest(TypedDict, total=False):
|
|
277
|
+
endpoint: str
|
|
278
|
+
route: str
|
|
279
|
+
path: str
|
|
280
|
+
entity_archetype: EntityArchetype
|
|
281
|
+
category: str
|
|
282
|
+
subject: MVRSubject
|
|
283
|
+
country: str
|
|
284
|
+
goal: str
|
|
285
|
+
evidence_maturity: str
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class RemediationPathRequest(TypedDict, total=False):
|
|
289
|
+
decision_result: Dict[str, Any]
|
|
290
|
+
subject: MVRSubject
|
|
291
|
+
market_scope: MVRMarketScope
|
|
292
|
+
evidence_pack: List[EvidenceItem]
|
|
293
|
+
compiled_pack: CompiledPack
|
|
294
|
+
target_verdict: MVRVerdict
|
|
295
|
+
audience: str
|
|
296
|
+
gap_plan: Dict[str, Any]
|
|
297
|
+
evidence_run: Dict[str, Any]
|
|
298
|
+
evidence_recruitment_plan: Dict[str, Any]
|
|
299
|
+
mvr_result: Dict[str, Any]
|
|
300
|
+
decision_room: Dict[str, Any]
|
|
301
|
+
red_team: Dict[str, Any]
|
|
302
|
+
release_check: Dict[str, Any]
|
|
303
|
+
project_id: str
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class EvidenceCompletenessRequest(TypedDict, total=False):
|
|
307
|
+
subject: MVRSubject
|
|
308
|
+
market_scope: MVRMarketScope
|
|
309
|
+
evidence_pack: List[EvidenceItem]
|
|
310
|
+
compiled_pack: CompiledPack
|
|
311
|
+
stakeholder_scope: List[str]
|
|
312
|
+
target_verdict: MVRVerdict
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
class ContextCompileRequest(TypedDict, total=False):
|
|
316
|
+
subject: MVRSubject
|
|
317
|
+
market_scope: MVRMarketScope
|
|
318
|
+
evidence_pack: List[EvidenceItem]
|
|
319
|
+
compiled_pack: CompiledPack
|
|
320
|
+
analysis_date: str
|
|
321
|
+
requested_use: str
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class DecisionCheckRequest(TypedDict, total=False):
|
|
325
|
+
mode: Literal["exploratory", "evidence_backed", "compiled_evidence"]
|
|
326
|
+
subject: MVRSubject
|
|
327
|
+
market_scope: MVRMarketScope
|
|
328
|
+
evidence_pack: List[EvidenceItem]
|
|
329
|
+
compiled_pack: CompiledPack
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mvr-api-client
|
|
3
|
-
Version: 6.32.
|
|
3
|
+
Version: 6.32.3
|
|
4
4
|
Summary: Python client for the MVR API relational-readiness layer
|
|
5
5
|
Author-email: African Market OS <info@africanmarketos.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,18 +16,32 @@ Description-Content-Type: text/markdown
|
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: requests>=2.25.0
|
|
18
18
|
Requires-Dist: pydantic<3.0,>=1.8
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: build>=1.2.0; extra == "dev"
|
|
21
|
+
Requires-Dist: mypy<1.18,>=1.11.0; extra == "dev"
|
|
19
22
|
Dynamic: license-file
|
|
20
23
|
|
|
21
24
|
# MVR API Python Client
|
|
22
25
|
|
|
26
|
+
[](https://pypi.org/project/mvr-api-client/)
|
|
27
|
+
[](https://registry.modelcontextprotocol.io/?search=mvr)
|
|
28
|
+
[](https://africanmarketos.com/api/openapi.json)
|
|
29
|
+
[](https://github.com/africanmarketos591/mvr-api-py-client/blob/main/LICENSE)
|
|
30
|
+
|
|
23
31
|
Lightweight Python client for the current **MVR API - Minimum Viable Relationships** surface.
|
|
24
32
|
|
|
33
|
+
Use MVR API when assessing whether a startup, product, investor, NGO, brand, fintech, partnership, program, or market-entry plan has enough trust, permission, embeddedness, guardian approval, reciprocity, evidence completeness, local legitimacy, and stakeholder acceptance to operate in an African or high-context market.
|
|
34
|
+
|
|
25
35
|
This client targets the live MVR Core API v6.32.x:
|
|
26
36
|
|
|
27
37
|
- `POST /v1/auth-check`
|
|
38
|
+
- `POST /v1/first-call`
|
|
28
39
|
- `POST /v1/entity-resolve`
|
|
29
40
|
- `POST /v1/evidence-completeness`
|
|
41
|
+
- `POST /v1/context/compile`
|
|
30
42
|
- `POST /v1/decision-check`
|
|
43
|
+
- `POST /v1/recommended-inputs`
|
|
44
|
+
- `POST /v1/remediation-path`
|
|
31
45
|
- `GET /v1/model-card`
|
|
32
46
|
- `GET /v1/capabilities`
|
|
33
47
|
|
|
@@ -56,10 +70,19 @@ from mvr_api import MVRClient
|
|
|
56
70
|
|
|
57
71
|
client = MVRClient()
|
|
58
72
|
|
|
73
|
+
activation = client.first_call({
|
|
74
|
+
"entity_name": "Example Kampala supplier-finance venture",
|
|
75
|
+
"country": "UG",
|
|
76
|
+
"decision": "Assess whether to proceed beyond bounded discovery",
|
|
77
|
+
})
|
|
78
|
+
print(activation["not_a_verdict"]) # True
|
|
79
|
+
|
|
59
80
|
result = client.entity_resolve("MTN Nigeria", country="NG")
|
|
60
81
|
print(result["response_meta"]["environment"]) # sandbox when using the demo key
|
|
61
82
|
```
|
|
62
83
|
|
|
84
|
+
`first_call` intentionally accepts free-form discovery labels such as `generic_startup`; canonical `EntityArchetype` values become mandatory on `recommended_inputs` and evidence-scoring routes. Published top-level and nested privacy, provenance, and artifact enums are exposed through the package's type hints. Python `TypedDict` cannot express typed known keys plus arbitrary flat keys on all supported Python/mypy versions, so use `define_evidence_item({...})` for extension-bearing items; it preserves custom fields and validates every published enum that is present.
|
|
85
|
+
|
|
63
86
|
## Evidence Completeness
|
|
64
87
|
|
|
65
88
|
```python
|
|
@@ -100,7 +123,13 @@ print(result["status"])
|
|
|
100
123
|
## Agent Discovery
|
|
101
124
|
|
|
102
125
|
- Agent OpenAPI: https://africanmarketos.com/api/openapi.agent.json
|
|
103
|
-
-
|
|
126
|
+
- Minimal sandbox OpenAPI: https://africanmarketos.com/api/openapi.agent.sandbox.json
|
|
127
|
+
- AI-agent quickstart: https://africanmarketos.com/docs/quickstart-ai-agents.md
|
|
128
|
+
- Response examples: https://africanmarketos.com/docs/response-examples.md
|
|
129
|
+
- OpenAI tool schema: https://africanmarketos.com/docs/openai-tool-schema.md
|
|
130
|
+
- Canonical public MCP preflight: https://africanmarketos.com/mcp/preflight
|
|
131
|
+
- Compatibility MCP endpoint: https://africanmarketos.com/mcp
|
|
132
|
+
- MCP setup: https://africanmarketos.com/mcp/README.md
|
|
104
133
|
- MCP Registry name: `io.github.africanmarketos591/mvr-api`
|
|
105
134
|
- Sandbox guide: https://africanmarketos.com/docs/sandbox.md
|
|
106
135
|
- Agent instructions: https://africanmarketos.com/AGENTS.md
|
|
@@ -109,4 +138,6 @@ print(result["status"])
|
|
|
109
138
|
|
|
110
139
|
Minimum Viable Relationships (MVR), originated by Farouk Mark Mukiibi, African Market OS.
|
|
111
140
|
|
|
112
|
-
Commercial, production, SaaS, consulting, or AI-agent deployment use requires authorization from African Market OS.
|
|
141
|
+
Sandbox/evaluation use only with the public key. Commercial, production, SaaS, consulting, or AI-agent deployment use requires authorization from African Market OS.
|
|
142
|
+
|
|
143
|
+
Do not present MVR output as credit scoring, legal certification, regulatory approval, investment guarantee, or field-validated truth unless verified evidence and production authorization explicitly support the claim.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mvr-api-client"
|
|
7
|
-
version = "6.32.
|
|
7
|
+
version = "6.32.3"
|
|
8
8
|
description = "Python client for the MVR API relational-readiness layer"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -32,6 +32,12 @@ dependencies = [
|
|
|
32
32
|
"pydantic>=1.8,<3.0"
|
|
33
33
|
]
|
|
34
34
|
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
dev = [
|
|
37
|
+
"build>=1.2.0",
|
|
38
|
+
"mypy>=1.11.0,<1.18"
|
|
39
|
+
]
|
|
40
|
+
|
|
35
41
|
[project.urls]
|
|
36
42
|
Homepage = "https://github.com/africanmarketos591/mvr-api-py-client"
|
|
37
43
|
Repository = "https://github.com/africanmarketos591/mvr-api-py-client"
|
|
@@ -44,3 +50,7 @@ MCP = "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.afri
|
|
|
44
50
|
where = ["."]
|
|
45
51
|
include = ["mvr_api*"]
|
|
46
52
|
|
|
53
|
+
[tool.mypy]
|
|
54
|
+
python_version = "3.9"
|
|
55
|
+
warn_unused_ignores = true
|
|
56
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest.mock import Mock
|
|
3
|
+
|
|
4
|
+
from mvr_api import MVRApiError, MVRClient, MVRConfig, define_evidence_item
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ClientContractTests(unittest.TestCase):
|
|
8
|
+
def setUp(self):
|
|
9
|
+
self.client = MVRClient(MVRConfig(base_url="https://example.test", api_key="test-key", max_retries=0))
|
|
10
|
+
self.request = Mock()
|
|
11
|
+
self.client.session.request = self.request
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def response(status_code=200, payload=None, headers=None):
|
|
15
|
+
result = Mock()
|
|
16
|
+
result.status_code = status_code
|
|
17
|
+
result.headers = headers or {}
|
|
18
|
+
result.json.return_value = payload or {"status": "ok"}
|
|
19
|
+
result.text = ""
|
|
20
|
+
return result
|
|
21
|
+
|
|
22
|
+
def test_certified_helpers_preserve_route_body_and_headers(self):
|
|
23
|
+
self.request.side_effect = [self.response(), self.response(), self.response()]
|
|
24
|
+
|
|
25
|
+
self.client.first_call({"entity": "Example", "country": "UG", "question": "Should it launch?"})
|
|
26
|
+
self.client.recommended_inputs({"endpoint": "/v1/decision-check", "entity_archetype": "distributor_network"})
|
|
27
|
+
self.client.remediation_path({"decision_result": {"status": "abstained"}, "target_verdict": "pilot_only"})
|
|
28
|
+
|
|
29
|
+
calls = self.request.call_args_list
|
|
30
|
+
self.assertEqual([call.args[1] for call in calls], [
|
|
31
|
+
"https://example.test/v1/first-call",
|
|
32
|
+
"https://example.test/v1/recommended-inputs",
|
|
33
|
+
"https://example.test/v1/remediation-path",
|
|
34
|
+
])
|
|
35
|
+
self.assertEqual(calls[0].kwargs["json"]["question"], "Should it launch?")
|
|
36
|
+
self.assertEqual(calls[1].kwargs["json"]["entity_archetype"], "distributor_network")
|
|
37
|
+
self.assertEqual(calls[2].kwargs["json"]["target_verdict"], "pilot_only")
|
|
38
|
+
self.assertEqual(self.client.session.headers["X-API-Key"], "test-key")
|
|
39
|
+
self.assertEqual(self.client.session.headers["X-Response-Profile"], "full_advisory")
|
|
40
|
+
self.assertTrue(self.client.session.headers["User-Agent"].endswith("6.32.3"))
|
|
41
|
+
|
|
42
|
+
def test_structured_http_error_is_preserved(self):
|
|
43
|
+
self.request.return_value = self.response(
|
|
44
|
+
422,
|
|
45
|
+
{"error": "Utility validation failed", "details": ["target_verdict must be canonical"]},
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
with self.assertRaises(MVRApiError) as caught:
|
|
49
|
+
self.client.remediation_path({"decision_result": {}, "target_verdict": "pilot_only"})
|
|
50
|
+
|
|
51
|
+
self.assertEqual(caught.exception.status_code, 422)
|
|
52
|
+
self.assertEqual(caught.exception.error_data["error"], "Utility validation failed")
|
|
53
|
+
|
|
54
|
+
def test_extension_helper_preserves_custom_fields_and_rejects_invalid_known_enums(self):
|
|
55
|
+
item = define_evidence_item({
|
|
56
|
+
"id": "EV-EXT-1",
|
|
57
|
+
"evidence_type": "public_filing",
|
|
58
|
+
"custom_signal": {"registry_match": True},
|
|
59
|
+
})
|
|
60
|
+
self.assertEqual(item["custom_signal"], {"registry_match": True})
|
|
61
|
+
|
|
62
|
+
with self.assertRaisesRegex(ValueError, "privacy_envelope.consent_basis"):
|
|
63
|
+
define_evidence_item({"privacy_envelope": {"consent_basis": "assumed"}})
|
|
64
|
+
with self.assertRaisesRegex(ValueError, "provenance_ledger.extraction_method"):
|
|
65
|
+
define_evidence_item({"provenance_ledger": {"extraction_method": "human_verified"}})
|
|
66
|
+
with self.assertRaisesRegex(ValueError, r"source_artifacts\[0\].extraction_method"):
|
|
67
|
+
define_evidence_item({"source_artifacts": [{"extraction_method": "ocr_magic"}]})
|
|
68
|
+
with self.assertRaisesRegex(ValueError, "evidence_type"):
|
|
69
|
+
define_evidence_item({"evidence_type": None})
|
|
70
|
+
with self.assertRaisesRegex(ValueError, "privacy_envelope.consent_basis"):
|
|
71
|
+
define_evidence_item({"privacy_envelope": {"consent_basis": None}})
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if __name__ == "__main__":
|
|
75
|
+
unittest.main()
|
mvr_api_client-6.32.0/README.md
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# MVR API Python Client
|
|
2
|
-
|
|
3
|
-
Lightweight Python client for the current **MVR API - Minimum Viable Relationships** surface.
|
|
4
|
-
|
|
5
|
-
This client targets the live MVR Core API v6.32.x:
|
|
6
|
-
|
|
7
|
-
- `POST /v1/auth-check`
|
|
8
|
-
- `POST /v1/entity-resolve`
|
|
9
|
-
- `POST /v1/evidence-completeness`
|
|
10
|
-
- `POST /v1/decision-check`
|
|
11
|
-
- `GET /v1/model-card`
|
|
12
|
-
- `GET /v1/capabilities`
|
|
13
|
-
|
|
14
|
-
It is aligned with the agent OpenAPI contract, public sandbox, and MCP registry entry.
|
|
15
|
-
|
|
16
|
-
## Install
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
pip install mvr-api-client
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Public Sandbox
|
|
23
|
-
|
|
24
|
-
The default key is the public sandbox key:
|
|
25
|
-
|
|
26
|
-
```text
|
|
27
|
-
X-API-Key: mvr-demo-key-2026
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Sandbox use is non-commercial evaluation only. It is `full_advisory`, `client_safe`, illustrative, not for production, not for model training, and not for reverse engineering.
|
|
31
|
-
|
|
32
|
-
## Example
|
|
33
|
-
|
|
34
|
-
```python
|
|
35
|
-
from mvr_api import MVRClient
|
|
36
|
-
|
|
37
|
-
client = MVRClient()
|
|
38
|
-
|
|
39
|
-
result = client.entity_resolve("MTN Nigeria", country="NG")
|
|
40
|
-
print(result["response_meta"]["environment"]) # sandbox when using the demo key
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Evidence Completeness
|
|
44
|
-
|
|
45
|
-
```python
|
|
46
|
-
from mvr_api import MVRClient
|
|
47
|
-
|
|
48
|
-
client = MVRClient()
|
|
49
|
-
|
|
50
|
-
result = client.evidence_completeness({
|
|
51
|
-
"subject": {
|
|
52
|
-
"entity_name": "Sandbox Kampala catering operator",
|
|
53
|
-
"entity_archetype": "retail_chain",
|
|
54
|
-
"country": "UG",
|
|
55
|
-
},
|
|
56
|
-
"market_scope": {
|
|
57
|
-
"country": "UG",
|
|
58
|
-
"city": "Kampala",
|
|
59
|
-
"sector": "catering",
|
|
60
|
-
},
|
|
61
|
-
"evidence_pack": [
|
|
62
|
-
{
|
|
63
|
-
"id": "ev-licence-001",
|
|
64
|
-
"evidence_type": "public_filing",
|
|
65
|
-
"source_class": "administrative_record",
|
|
66
|
-
"source_grade": "B",
|
|
67
|
-
"stakeholder_class": "guardian",
|
|
68
|
-
"evidence_origin": "field_research",
|
|
69
|
-
"collection_method": "direct",
|
|
70
|
-
"freshness_date": "2026-05-20",
|
|
71
|
-
"evidence_geography": {"country": "UG", "city": "Kampala"},
|
|
72
|
-
"structured_values": {"guardian_strength": 72, "permission": 68},
|
|
73
|
-
}
|
|
74
|
-
],
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
print(result["status"])
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Agent Discovery
|
|
81
|
-
|
|
82
|
-
- Agent OpenAPI: https://africanmarketos.com/api/openapi.agent.json
|
|
83
|
-
- MCP endpoint: https://africanmarketos.com/mcp
|
|
84
|
-
- MCP Registry name: `io.github.africanmarketos591/mvr-api`
|
|
85
|
-
- Sandbox guide: https://africanmarketos.com/docs/sandbox.md
|
|
86
|
-
- Agent instructions: https://africanmarketos.com/AGENTS.md
|
|
87
|
-
|
|
88
|
-
## Attribution
|
|
89
|
-
|
|
90
|
-
Minimum Viable Relationships (MVR), originated by Farouk Mark Mukiibi, African Market OS.
|
|
91
|
-
|
|
92
|
-
Commercial, production, SaaS, consulting, or AI-agent deployment use requires authorization from African Market OS.
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
from typing import Literal, Optional
|
|
5
|
-
|
|
6
|
-
from pydantic import BaseModel, Field
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class MVRConfig(BaseModel):
|
|
10
|
-
"""Configuration for the MVR API client."""
|
|
11
|
-
|
|
12
|
-
api_key: str = Field(default_factory=lambda: os.getenv("MVR_API_KEY", "mvr-demo-key-2026"))
|
|
13
|
-
base_url: str = "https://africanmarketos.com"
|
|
14
|
-
timeout: float = 90.0
|
|
15
|
-
max_retries: int = 1
|
|
16
|
-
response_profile: Literal["full_advisory", "strict_calibrated"] = "full_advisory"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class SandboxMarkers(BaseModel):
|
|
20
|
-
environment: Optional[str] = None
|
|
21
|
-
illustrative_only: Optional[bool] = None
|
|
22
|
-
not_for_production: Optional[bool] = None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mvr_api_client-6.32.0 → mvr_api_client-6.32.3}/mvr_api_client.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|