Skip to content

[FEATURE] Draft Support for CAP MCP Plugin #116

Description

@Mhidayah19

Description

The CAP MCP Plugin currently lacks support for creating and managing draft entities in SAP CAP (Cloud Application Programming) applications. This prevents AI assistants and MCP clients from interacting with draft-enabled entities in a way that matches OData behavior, leading to critical issues:
Key Problems Solved:

  1. Invisible Drafts: Draft entities created via MCP tools don't appear in Fiori UI because the critical DraftAdministrativeData record wasn't being created
  2. Composition Child Failures: Creating composition children (e.g., attachments, line items) under draft parents failed with service resolution errors
  3. Lifecycle Bypass: Direct INSERT operations bypassed CAP's draft lifecycle handlers, missing essential metadata population
    Use Cases:
  • AI-assisted data entry: Allow AI assistants to create and edit draft documents (e.g., purchase orders, consumption requests) that users can review before activation
  • Multi-step workflows: Support complex business processes where AI helps populate draft records that require human approval
  • Attachment handling: Enable AI to add attachments and related items to draft parent entities
  • Draft management: Allow AI to query, update, and delete draft entities with proper user context
    Benefits:
  • Fiori Integration: Drafts created via MCP are fully visible and manageable in Fiori UIs
  • CAP Compliance: Uses CAP's official draft lifecycle (svc.send('NEW')) instead of bypassing it
  • User Context: Properly links drafts to the authenticated user via DraftAdministrativeData
  • Consistency: MCP-created drafts are structurally identical to OData-created drafts
  • Composition Support: Handles nested composition children that inherit draft behavior from parents

Suggested Solution

Implement comprehensive draft support through three components, each addressing a specific gap:

1. Root Draft Entity Creation

Before:

  • Used direct INSERT operations: svc.run(INSERT.into(entity.drafts).entries(data))
  • Bypassed CAP's draft lifecycle handlers
  • Created draft record but NO DraftAdministrativeData
  • ❌ Drafts invisible in Fiori UI
    After:
  • Use CAP's official draft API: svc.send('NEW', draftEntityDef, data)
  • Triggers CAP's onNew() handler which creates BOTH draft record AND DraftAdministrativeData
  • ✅ Drafts appear in Fiori UI
  • ✅ User context properly tracked (InProcessByUser, DraftIsCreatedByMe)
  • ✅ Structurally identical to OData-created drafts

2. Draft Composition Child Support

Before:

  • Composition children (e.g., attachments under draft documents) routed to regular INSERT path
  • ❌ Error: Service not found: ConsumptionService.ConsumptionRequests
  • ❌ Error: table has no column named hash (@Core.Computed fields included in SQL)
  • ❌ Error: NOT NULL constraint on DraftAdministrativeData_DraftUUID
    After:
  • Runtime detection of draft composition children (they inherit .drafts from parent)
  • Use explicit .columns().values() INSERT to exclude computed fields
  • Auto-resolve parent's DraftAdministrativeData_DraftUUID via lookup
  • ✅ Composition children successfully created under draft parents
  • ✅ Correctly reference same DraftAdministrativeData as parent
  • ✅ No computed field errors

3. Improved Entity Name Parsing

Before:

  • Naive split on last dot: "Service.Entity.SubEntity" → service: "Service.Entity"
  • ❌ Service resolution fails for nested entities
    After:
  • Longest-prefix matching against known service names
  • "ConsumptionService.ConsumptionRequests.chargeSheets" → service: "ConsumptionService"
  • ✅ Correct service resolution for all entity depths

Result Summary

Metric Before After
Root drafts in Fiori ❌ Invisible ✅ Visible
DraftAdministrativeData ❌ Missing ✅ Created
Composition children ❌ Failed ✅ Working
Nested entity parsing ❌ Incorrect ✅ Correct
Test coverage ❌ No draft tests ✅ 787 tests passing

Alternatives

Alternative 1: Direct .drafts INSERT (Rejected)

svc.run(INSERT.into(entity.drafts).entries(data));

Issues:

  • Bypasses CAP's draft lifecycle
  • No DraftAdministrativeData created
  • Drafts invisible in Fiori UI

Alternative 2: Use svc.post() (Rejected)

svc.post(`${entity}.drafts`, data);

Issues:

  • Still bypasses onNew() handler
  • Missing draft metadata
  • Not the official CAP draft API

Alternative 3: Manual DraftAdministrativeData Creation (Rejected)

// Manually insert draft record
await INSERT.into(entity.drafts).entries(data);
// Manually insert administrative data
await INSERT.into('DraftAdministrativeData').entries({...});

Issues:

  • Fragile and error-prone
  • Doesn't match CAP's internal implementation
  • May break with CAP version updates
  • Doesn't respect draft validation rules

Additional Context

References

SAP CAP Documentation

  • Draft Support - Official CAP documentation on implementing draft-enabled entities

Related CAP Concepts

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions