jxyedw opened a new issue, #253:
URL: https://github.com/apache/doris-mcp-server/issues/253

   ## Summary
   
   When both optional semantic providers are enabled, `doris_semantic` domain 
discovery fails with `DomainManifestBudgetError`.
   
   The `doris_semantic` manifest contains all 12 children (4 Ossie + 8 
MetricFlow). With both providers enabled, the canonical JSON manifest is 
**16,747 bytes**, which is **363 bytes over** the hard-coded `16 KiB` domain 
manifest budget.
   
   As a result, Ossie grounding and MetricFlow query cannot be used from the 
same server process, even though the 1.0 design (#175) and the public 
documentation describe them as two parts of the same `doris_semantic` domain.
   
   ## Environment
   
   - `doris-mcp-server`: `1.0.0` (tag; tested checkout `953c3b6`)
   - MCP protocol: `2026-07-28`
   - Transport: `stdio`
   - Exposure mode: `hierarchical` (default); flat mode also reproduced
   - Python: `3.12.13`
   - Doris: `4.0.1-rc02` (FE/BE)
   - Ossie model: 4 datasets / 7 metrics / 3 relationships, 
`mapping_status=resolved`
   - MetricFlow: `0.213.0` via the `doris-mcp-metricflow/v1` sidecar
   - Auth: local stdio (no OAuth); the issue is about manifest size, not 
authorization
   
   ## Steps to reproduce
   
   1. Start the server with the Ossie provider enabled:
   
   ```bash
   OSSIE_ENABLED=true
   OSSIE_MODEL_DIRECTORY=<ossie-model-dir>
   OSSIE_BINDING_MANIFEST=<ossie-binding-manifest>
   METRICFLOW_ENABLED=false
   ```
   
   2. Call `doris_semantic` with `{}`; discovery succeeds.
   
   3. Restart with both providers enabled:
   
   ```bash
   OSSIE_ENABLED=true
   OSSIE_MODEL_DIRECTORY=<ossie-model-dir>
   OSSIE_BINDING_MANIFEST=<ossie-binding-manifest>
   METRICFLOW_ENABLED=true
   METRICFLOW_PROVIDER_COMMAND_JSON=["<python>","<metricflow-provider.py>"]
   METRICFLOW_PROJECT_DIRECTORY=<metricflow-project-dir>
   ```
   
   4. Call `doris_semantic` with `{}` again. Discovery fails with 
`DomainManifestBudgetError`.
   
   The public error message is redacted, but the stack points to:
   
   ```text
   doris_mcp_server/tools/domain_manifest.py:770
   raise DomainManifestBudgetError(...)
   ```
   
   In flat mode, `tools/list` fails earlier with the same error.
   
   ## Measured manifest sizes
   
   The numbers below are canonical JSON sizes, measured as:
   
   ```python
   len(envelope.to_canonical_json().encode("utf-8"))
   ```
   
   | Configuration | Children | Manifest size | Result |
   |---|---:|---:|---|
   | MetricFlow only | 12 (4 Ossie `misconfigured`, 8 MF `degraded`) | **15,747 
B** | passes, only 637 B headroom |
   | Ossie only | 12 (4 Ossie `available/degraded`, 8 MF `misconfigured`) | 
**13,041 B** | passes |
   | Both providers enabled | 12 (all `available/degraded`) | **16,747 B** | 
**fails, 363 B over the 16,384 B limit** |
   
   For the both-enabled case, I could not capture the exact byte count from the 
failing server because the error message is redacted. I reconstructed it by 
taking the 8 MetricFlow child entries from the MetricFlow-only manifest and the 
4 Ossie child entries from the Ossie-only manifest. The flat-mode run fails 
with the same `DomainManifestBudgetError`.
   
   ### Where the extra ~1 KiB comes from
   
   The 8 MetricFlow entries are identical in both single-provider runs. The 
growth comes from the 4 Ossie entries changing from `misconfigured` to 
`available/degraded`:
   
   | Ossie child | MetricFlow-only (`misconfigured`) | Both enabled 
(`available/degraded`) | Delta |
   |---|---:|---:|---:|
   | `list_semantic_models` | 751 B | 884 B | +133 B |
   | `get_semantic_model_summary` | 818 B | 1,093 B | +275 B |
   | `get_semantic_context` | 1,230 B | 1,519 B | +289 B |
   | `get_semantic_mapping_status` | 833 B | 1,136 B | +303 B |
   | **Total** | | | **+1,000 B** |
   
   The extra bytes are `availability` metadata (`detected_versions`, 
`evidence_sources`, `limitations`, `active_variant`) plus the dynamic 
description prefix.
   
   ## Root cause
   
   - `MAX_DOMAIN_MANIFEST_BYTES = 16 * 1024` is hard-coded in 
`doris_mcp_server/tools/domain_models.py`.
   - `DomainDefinition.max_manifest_bytes` is constrained to `<= 
MAX_DOMAIN_MANIFEST_BYTES`, so an operator cannot raise it.
   - `domain_manifest.py::_build_manifest` raises `DomainManifestBudgetError` 
when the serialized envelope exceeds the budget.
   - `doris_semantic` has 12 children, which is the maximum allowed by 
`DomainDefinition.children` (`Field(max_length=12)`).
   - All 12 children are always included; children from a disabled provider are 
marked `misconfigured` and remain visible.
   - There is no pagination, lazy child schema, or partial manifest. One 
oversized entry fails the whole domain.
   
   This is a capacity/packaging issue: the domain is at the maximum child 
count, and enabling both optional providers adds enough `availability` metadata 
to exceed the budget.
   
   ## Impact
   
   - Ossie and MetricFlow cannot be enabled together in one server process; 
operators must run two profiles/processes and callers need two endpoints.
   - This contradicts the design intent in #175 (`doris_semantic` remains the 
domain; Ossie is the model contract; MetricFlow is an optional provider; both 
paths are supported).
   - It also conflicts with the documented behavior that optional integrations 
"stay visible but fail closed when called": here the whole domain fails at 
discovery, before the caller can see or call the available children.
   - The MetricFlow-only case has only **637 B** headroom, so it is fragile as 
well: a small future schema/availability addition can break the single-provider 
profile too.
   
   ## Suggested fixes
   
   1. **Split the domain (preferred)**
      - `doris_semantic_metricflow` (8 children, ~7.4 KiB)
      - `doris_semantic_ossie` (4 children, ~3.3 KiB)
      - This keeps each manifest comfortably within the budget and makes the 
provider boundary explicit.
   
   2. **Make the per-domain manifest budget configurable**
      - Default remains 16 KiB for safety.
      - Allow trusted deployments to raise it (for example, up to 64 KiB) with 
explicit validation and documentation.
      - This is the smallest code change, but it needs a decision on the 
security/DoS bound.
   
   3. **Add manifest pagination or lazy child schema loading**
      - This is a larger protocol change and probably out of scope for 1.0.x.
   
   ## Additional context
   
   - The public documentation does not mention the 16 KiB number; it only says 
that domain discovery has "manifest byte budgets" 
(`docs/operations/reliability.md`). The 16 KiB value is a source constant.
   - `master` still contains `MAX_DOMAIN_MANIFEST_BYTES = 16 * 1024` as of 
2026-11-09.
   - Flat mode is not a workaround: the 12 semantic flat tools alone serialize 
to ~35.9 KiB, and `MAX_TOP_LEVEL_TOOL_LIST_BYTES` is 24 KiB.
   
   Could maintainers confirm whether this is a known limitation and which fix 
direction is acceptable? I can provide a minimal reproduction harness or 
sanitized model/binding files if useful.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to