Swiftorial Logo
Home
Swift Lessons
AI Tools
Learn More
Career
Resources

From APIs to Agent Tools: Wrapping Enterprise Services with MCP

A clean, practical guide to converting your existing REST, GraphQL, gRPC, and data systems into MCP tools & resources that AI agents can discover, invoke, and govern—without rewriting your backend.

1) Why Wrap APIs as MCP Tools?

Enterprises already have hundreds of APIs. MCP (Model/Modal Context Protocol) lets you expose those capabilities to AI agents through a uniform, schema-driven interface. Instead of brittle prompt-based HTTP calls, agents invoke clearly defined tools (actions) and resources (read-only data) with JSON schemas, while your platform applies the same governance you use for APIs.

  • Consistency: One interface for many backends (REST/GraphQL/gRPC/DB).
  • Safety: Schema validation, RBAC/ABAC, audit trails.
  • Velocity: Runtime discovery; no per-agent glue code.
  • Reuse: Generate tools from OpenAPI specs to avoid rework.

2) Architecture: Mapping Providers to Agent-Ready Capabilities

MCP follows a client–server model. Your agent or host app is the MCP client; your wrapper service is the MCP server exposing a catalog of tools/resources.

Agent (MCP Client)
  └─> Handshake (discover catalog)
      ├─ tools: actions (createOrder, refund, schedulePickup)
      ├─ resources: read contexts (customerProfile, inventoryAt)
      └─ prompts: reusable instruction templates (optional)

MCP Server
└─> Calls existing systems: REST / GraphQL / gRPC / DB / SaaS
(auth, retries, mapping, error normalization happen here)

Rule of thumb: expose “verbs” as tools (mutations, commands) and “nouns/queries” as resources (read-only, cacheable).

3) Wrapping REST, GraphQL, gRPC, and Datastores

3.1 REST → Tools/Resources

// REST endpoints
GET /v1/customers/{id}           → resource: customerProfile(id)
POST /v1/orders                  → tool: createOrder(customerId, items[])
POST /v1/orders/{id}/refund      → tool: refundOrder(orderId, reason)
```

3.2 GraphQL → Tools/Resources

// GraphQL
```

query getCustomer(\$id: ID!)      → resource: customerProfile(id)
mutation createOrder(...)         → tool: createOrder(...)
```

3.3 gRPC → Tools/Resources

// gRPC
```

rpc CreateShipment(CreateShipmentRequest) returns (Shipment)
→ tool: createShipment(orderId, address, method)
```

3.4 DB/Analytics → Resources

// SQL/warehouse
```

SELECT \* FROM inventory WHERE sku=? AND location=?
→ resource: inventoryAt(sku, location)

4) Designing Tools: Names, Schemas, Idempotency, Errors

Keep tools stable, descriptive, and documented via JSON Schema. Treat them like public functions.

  • Naming: lowerCamelCase verbs (e.g., createOrder, refundOrder).
  • Input/Output: precise JSON Schemas; enums for states; types for money/dates.
  • Idempotency: support idempotencyKey for safe retries on tools with side effects.
  • Error envelope: consistent shape for validation/business/system errors.

Tool Definition (Conceptual)

{
  "name": "createOrder",
  "description": "Create a new order for a customer",
  "inputSchema": {
    "type": "object",
    "properties": {
      "customerId": {"type":"string"},
      "items": {
        "type":"array",
        "items":{"type":"object","properties":{"sku":{"type":"string"},"qty":{"type":"integer","minimum":1}},"required":["sku","qty"]}
      },
      "idempotencyKey": {"type":"string"}
    },
    "required": ["customerId","items"]
  },
  "outputSchema": {
    "type":"object",
    "properties": {
      "orderId":{"type":"string"},
      "status":{"type":"string","enum":["pending","paid","shipped","canceled"]}
    },
    "required":["orderId","status"]
  }
}
```

Standard Error Model

{
```

"error": {
"code": "TOOL\_VALIDATION\_FAILED",
"message": "Missing item.sku at index 0",
"correlationId": "7e1a-...",
"details": {"field":"items\[0].sku"}
}
}

5) Designing Resources: Read-Only Contexts Done Right

  • Stable names: nouns (e.g., customerProfile, inventoryAt).
  • Parameters: minimal, explicit (id, sku, location).
  • Pagination & filtering: standard params; include nextCursor.
  • Caching: allow server-side caching; include asOf timestamps.

Resource Definition (Conceptual)

{
  "name":"customerProfile",
  "params":{"id":"string"},
  "schema":{
    "type":"object",
    "properties":{
      "id":{"type":"string"},
      "name":{"type":"string"},
      "email":{"type":"string"},
      "tier":{"type":"string","enum":["gold","silver","bronze"]},
      "asOf":{"type":"string","format":"date-time"}
    },
    "required":["id","name","asOf"]
  }
}

6) OpenAPI → MCP: Auto-Generate to Move Fast

Where possible, generate MCP tools/resources from your existing OpenAPI specs. A simple mapping works well:

// Mapping rules (example)
GET /v1/customers/{id}      → resource: customerProfile(id)
POST /v1/orders             → tool: createOrder(...)
POST /v1/orders/{id}/refund → tool: refundOrder(orderId, reason)

Tips: honor request/response schemas; convert validation rules to JSON Schema; carry over enums & examples; document auth scopes.

7) Security, Privacy & Governance

  • AuthN: OAuth2/OIDC for user-initiated flows; mTLS or workload identity for services.
  • AuthZ: RBAC for simplicity; ABAC for tenant/context-aware access; scope tools by purpose.
  • PII/Secrets: never echo sensitive outputs by default; allow redaction masks in schemas.
  • Audit: log caller, tool/resource, input keys (redacted), output type, latency, correlationId.

OPA/Rego Policy (Allow only orders:write)

package mcp.authz
default allow = false
allow {
  input.user.scopes[_] == "orders:write"
  input.tool.name == "createOrder"
}

8) Versioning & Deprecation: Side-by-Side, No Surprises

  • Expose createOrder_v1 and createOrder_v2 concurrently; document differences.
  • Mark deprecated tools/resources in the catalog; provide end-of-life dates.
  • Offer migration guides; instrument usage to identify lagging consumers.
// Catalog (excerpt)
"tools": [
  {"name":"createOrder_v1", "inputSchema":{...}, "outputSchema":{...}, "deprecated":true, "sunset":"2026-06-30"},
  {"name":"createOrder_v2", "inputSchema":{...}, "outputSchema":{...}}
]

9) CI/CD for MCP Servers

  • Lint: naming, error envelope, enum constraints, pagination standards.
  • Contract tests: schema-based validation for inputs/outputs.
  • Security scans: dep scanning, secret scanning, IaC checks for deploy configs.

Pipeline (Sketch)

name: mcp-ci
on: [pull_request]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Lint MCP catalog
        run: npx spectral lint mcp/catalog.json
      - name: Contract tests
        run: npm run test:contract
      - name: Security scan
        run: npx trivy fs --exit-code 1 .

10) Gateways, Mesh & Deployment

Run MCP servers behind your existing API gateway or mesh to reuse policies and observability.

# Pseudo gateway policy
route: /mcp/orders
upstream: mcp-orders.svc.cluster.local:8443
policies:
  - oauth2-jwt-verify
  - rate-limit: 600/min
  - schema-validate: ./mcp/orders-tools.json
  - waf: owasp-top-10

Mesh tips: enable mTLS, locality-aware routing, retries with budgets, and circuit breaking for downstream APIs.

11) Observability: Logs, Metrics, Traces

  • Logs: tool/resource name, version, caller, tenant, status, latency, correlationId.
  • Metrics: P50/P95 per tool, error rate, validation failure count, auth failures.
  • Tracing: propagate request IDs from agent → MCP server → provider APIs.
INFO mcp.call tool=createOrder_v2 status=200 latencyMs=183 user=svc-web tenant=retail corr=4f2a-...

12) Migration Playbook: Legacy → MCP

  1. Inventory: list top APIs by usage and business impact.
  2. Generate: create initial tools/resources from OpenAPI; normalize errors.
  3. Pilot: wrap one domain (e.g., Orders) and run an internal agent against it.
  4. Harden: add gateway policies, RBAC, audits; fix gaps found in pilot.
  5. Scale: roll out to adjacent domains; publish templates and CLI scaffolding.

13) Example Scenarios

13.1 Fulfillment Agent

Agent orchestrates reserveInventorycreateShipmentnotifyCustomer; errors trigger compensations (releaseInventory, cancelShipment).

13.2 Finance Close Assistant

Resources aggregate ledger snapshots; tools kick off reconciliation tasks; audit logs feed compliance.

13.3 Support Copilot

Resources fetch profile, orders, tickets; tools create cases, issue refunds, schedule callbacks—policy-gated.

14) Final Checklist & 30–60–90 Roadmap

Checklist

  • ✅ Clear tool/resource naming, stable schemas, idempotency for writes
  • ✅ Error envelope, correlation IDs, and standardized validation
  • ✅ Gateway policies (auth, rate limits, schema, WAF) and mesh mTLS
  • ✅ OpenAPI → MCP generation; CI lint + contract tests
  • ✅ Logs/metrics/traces; team scorecards and SLOs per tool
  • ✅ Versioning + deprecation policy with usage telemetry

30–60–90

Days 0–30:
• Pick one domain; generate initial tools/resources from OpenAPI
• Stand up MCP server behind gateway; add logs/metrics/traces
• Run a pilot agent; fix schema/latency/permission gaps

Days 31–60:
• Expand to 3–5 high-value APIs; publish to portal with docs/samples
• Enforce RBAC/ABAC, quotas; add contract tests and error budgets
• Launch CLI scaffolding + templates

Days 61–90:
• Make schema validation and CI checks mandatory for prod
• Introduce version/deprecation policy; start monthly scorecards
• Roll out to two more domains; plan multi-region if needed

15) FAQ

Q: Do I need to rewrite my APIs?
A: No. Wrap them. Start with OpenAPI→MCP generation and normalize errors/schemas.

Q: How do I prevent risky actions?
A: Scope tools, require approvals for sensitive ones, enforce RBAC/ABAC, and log every call.

Q: Is MCP only for agents?
A: It’s ideal for agents, but any app can act as an MCP client to gain the same standardized interface.

Takeaway: You don’t need to rebuild your backend for AI. Wrap what you already have with MCP, enforce standards and policies at the edge, and give agents a clean, universal way to act—safely and at scale.

← Back to Articles