Blog

Naftiko in Front of SAP CPI: Wrap, Don't Replace

Kin Lane ·April 8, 2026
Table of contents

SAP Cloud Integration (CPI) is a mature, enterprise-grade iPaaS. It is strong on certified SAP-to-SAP connectors, BPMN-style integration flows, mapping tools, security, and operations inside the SAP ecosystem. Most large SAP customers already have it, already pay for it, and already have iflows running in production.

Trying to displace SAP CPI on its home turf is a losing game. So Naftiko isn’t going to. Naftiko’s job is to make the CPI investment those enterprises already made safely usable by copilots and agents — without rewriting a single iflow.

This post walks through what that actually looks like as a Naftiko capability, with three real examples.

The pattern

SAP CPI iflows already expose REST or SOAP endpoints. A Naftiko capability consumes those endpoints and exposes them as MCP tools, Agent Skills, or governed REST — while reshaping the upstream SAP payload so the agent never sees raw SAP complexity. Field names get cleaned up. Verbose $.d.results envelopes get unwrapped. Multiple iflows get composed into single agent-task-shaped tools.

The whole capability lives in a single YAML file in Git. The Naftiko Engine reads it at runtime as a Docker container. There is no codegen, no rebuild of CPI, no second iPaaS to maintain.

Example 1: Wrap a single CPI iflow as an MCP tool

Common iflow: “Get open sales orders for a customer.” Already deployed on the CPI tenant. We want a copilot to be able to call it.

naftiko: "1.0.0-alpha1"

capability:
  name: sales-orders
  description: "Read open sales orders from SAP via existing CPI iflow"

  consumes:
    - namespace: cpi
      type: http
      baseUri: "https://my-tenant.it-cpi020.cfapps.eu10-002.hana.ondemand.com/http"
      auth:
        type: oauth2-client-credentials
        tokenUrl: "https://my-tenant.authentication.eu10.hana.ondemand.com/oauth/token"
        clientId: "${CPI_CLIENT_ID}"
        clientSecret: "${CPI_CLIENT_SECRET}"
      resources:
        - name: orders
          path: "/SalesOrders/v1/open"
          operations:
            - name: list-open-orders
              method: GET
              queryParameters:
                - name: customerId
                  type: string
                  required: true

  exposes:
    - type: mcp
      port: 3001
      namespace: sap-sales
      description: "SAP sales order tools"
      tools:
        - name: list-open-sales-orders
          description: "List open sales orders for a given customer"
          call: cpi.list-open-orders
          inputParameters:
            - name: customerId
              type: string
              description: "SAP customer ID (KUNNR)"
              mapping: "queryParameters.customerId"
          outputParameters:
            - type: array
              mapping: "$.d.results"
              items:
                type: object
                properties:
                  - name: orderId
                    type: string
                    mapping: "$.SalesOrderId"
                  - name: customerName
                    type: string
                    mapping: "$.SoldToParty"
                  - name: amount
                    type: number
                    mapping: "$.NetAmount"
                  - name: currency
                    type: string
                    mapping: "$.CurrencyCode"
                  - name: status
                    type: string
                    mapping: "$.OverallStatus"

What this gives you that CPI alone does not:

  • The whole integration lives in Git as one file
  • It exposes an MCP tool that Claude, Copilot, or Cursor can call directly
  • The verbose SAP envelope and field names are reshaped into clean agent-friendly outputs
  • Auth, upstream contract, and exposed contract are all visible in one inspectable place
  • Spectral can lint it (naming, identity propagation, required fields) before it ships

Example 2: Compose multiple CPI iflows into one capability

This is where Naftiko starts doing things CPI cannot easily do — composing across iflows into a single agent-task-shaped tool. An agent should not have to call three CPI endpoints to answer “what is the health of customer X?” It should call one tool. Three sources, one composed result.

naftiko: "1.0.0-alpha1"

capability:
  name: customer-360
  description: "Composed customer health view from SAP CPI"

  consumes:
    - namespace: cpi
      type: http
      baseUri: "https://my-tenant.it-cpi020.cfapps.eu10-002.hana.ondemand.com/http"
      auth:
        type: oauth2-client-credentials
        tokenUrl: "${CPI_TOKEN_URL}"
        clientId: "${CPI_CLIENT_ID}"
        clientSecret: "${CPI_CLIENT_SECRET}"
      resources:
        - name: customer
          path: "/Customers/v1/{customerId}"
          operations:
            - name: get-customer
              method: GET
        - name: orders
          path: "/SalesOrders/v1/open"
          operations:
            - name: list-open-orders
              method: GET
        - name: invoices
          path: "/Invoices/v1/overdue"
          operations:
            - name: list-overdue-invoices
              method: GET

  exposes:
    - type: mcp
      port: 3001
      namespace: sap-customer
      tools:
        - name: get-customer-health
          description: "Composed customer health summary including profile, open orders, and overdue invoices"
          inputParameters:
            - name: customerId
              type: string
              required: true
          steps:
            - call: cpi.get-customer
              with: { pathParameters.customerId: "${input.customerId}" }
              as: profile
            - call: cpi.list-open-orders
              with: { queryParameters.customerId: "${input.customerId}" }
              as: openOrders
            - call: cpi.list-overdue-invoices
              with: { queryParameters.customerId: "${input.customerId}" }
              as: overdueInvoices
          outputParameters:
            - type: object
              properties:
                - name: customerName
                  type: string
                  mapping: "${profile.d.SoldToParty}"
                - name: openOrderCount
                  type: integer
                  mapping: "${openOrders.d.results | length}"
                - name: openOrderValue
                  type: number
                  mapping: "${openOrders.d.results | sum(NetAmount)}"
                - name: overdueInvoiceCount
                  type: integer
                  mapping: "${overdueInvoices.d.results | length}"
                - name: overdueInvoiceValue
                  type: number
                  mapping: "${overdueInvoices.d.results | sum(Amount)}"
                - name: riskFlag
                  type: string
                  mapping: "${overdueInvoices.d.results | length > 0 ? 'at-risk' : 'healthy'}"

The agent calls one tool. Underneath, Naftiko orchestrates three CPI calls and composes them into a single small typed object. The model never sees three SAP envelopes. Token cost drops, accuracy goes up, and a security reviewer audits one capability instead of three loose tool wirings.

Example 3: Expose the same capability as MCP, Skill, and REST

Same underlying CPI integration, three surfaces, one declaration. CPI cannot do this without three separate iflows.

naftiko: "1.0.0-alpha1"

capability:
  name: invoice-lookup
  description: "Look up SAP invoices via CPI  exposed as MCP, Skill, and REST"

  consumes:
    - namespace: cpi
      type: http
      baseUri: "https://my-tenant.it-cpi020.cfapps.eu10-002.hana.ondemand.com/http"
      auth:
        type: oauth2-client-credentials
        tokenUrl: "${CPI_TOKEN_URL}"
        clientId: "${CPI_CLIENT_ID}"
        clientSecret: "${CPI_CLIENT_SECRET}"
      resources:
        - name: invoices
          path: "/Invoices/v1/{invoiceId}"
          operations:
            - name: get-invoice
              method: GET

  exposes:
    - type: mcp
      port: 3001
      namespace: sap-finance
      tools:
        - name: get-invoice
          call: cpi.get-invoice

    - type: skill
      port: 3002
      namespace: sap-finance-skill
      skills:
        - name: lookup-invoice
          call: cpi.get-invoice

    - type: rest
      port: 8080
      basePath: "/api/finance"
      endpoints:
        - method: GET
          path: "/invoices/{invoiceId}"
          call: cpi.get-invoice

One spec, one CPI upstream, three exposed surfaces — MCP for Claude and Copilot, Agent Skill for agent runtimes, REST for traditional callers. Same governed contract, same lint rules, same audit trail.

What this looks like in practice

The Naftiko Engine runs as a Docker container that reads these YAML files at startup. Drop them in a directory, run docker run, and you have:

  • An MCP server on :3001 that any MCP client can connect to
  • Optionally a Skill server on :3002
  • Optionally a REST server on :8080
  • All of them backed by your existing SAP CPI iflows
  • All of them governed by Spectral rules in CI and the VS Code extension
  • All of them inspectable in Git

Why this is the right wedge

The temptation, when you build an AI-native integration framework, is to position it against incumbent iPaaS platforms as a replacement. That is the wrong move with SAP CPI specifically. SAP customers have years of accumulated iflow investment, certified connectors, support contracts, and operational muscle memory. They are not going to throw it out because somebody wrote a blog post about MCP.

But they also know — every CTO and platform leader I talk to inside an SAP shop knows — that CPI was not designed for the agent era. There is no first-class concept of MCP servers, Agent Skills, or right-sized context outputs. There is no way to declaratively reshape a payload for a context window. There is no spec you can git diff, no Spectral lint, no IDE-level governance.

Naftiko fills exactly that gap, and it does so without asking the SAP customer to give anything up. You keep your iflows. You keep your CPI runtime. You keep your support contract. You drop a Naftiko capability YAML in front of the iflows you want agents to use, and you ship an MCP server your copilot can call this afternoon.

That is the positioning sentence:

Naftiko is not an iPaaS replacement for SAP Cloud Integration. It is the open, spec-driven, AI-native capability layer that makes your existing SAP integrations safely consumable by copilots and agents — without rebuilding what you already have.

What ships with this approach

Everything you need to do this is in the Naftiko Framework Alpha 1 (Apache 2.0), shipping now:

  • Declarative capability spec with consumes and exposes blocks
  • HTTP source adapter with OAuth2, basic, and bearer auth
  • MCP, Skill, and REST exposure types from a single capability
  • outputParameters for reshaping upstream payloads into clean typed outputs
  • Spectral ruleset for design-time governance
  • VS Code extension for live linting
  • Docker container for the engine — docker run and you are running

Try it

If you run SAP CPI and you are trying to figure out how to safely give your copilots and agents access to the integrations you already built, this is the ten-minute version of the answer. Pull the Docker image, point a Naftiko capability at one of your CPI endpoints, and ship an MCP server today.

Wrap, don’t replace.