Integration Guide

Code Execution
Integration Guide

Connect AI to Open Banking financial data using progressive disclosure. This guide explains how AI clients integrate with the OpenAgent Core ecosystem using the code execution approach — reducing token usage by 98%+ in typical workflows.

98%+ Token Reduction
34+ Tools
CDR Compliant
AI-Powered Insights
The Challenge

Why Code Execution with MCP?

When AI agents connect to MCP servers via direct tool calls, two critical problems emerge at scale.

Context Window Overload

Loading 34+ tool definitions upfront consumes hundreds of thousands of tokens before the agent can process a single request. This makes direct tool calls impractical at scale.

~150K tokensconsumed just loading definitions

Excessive Token Consumption

Large datasets — thousands of transactions, account histories — flow through the model multiple times, dramatically increasing cost and latency with every round-trip.

10,000+ rowspassing through context per query

The Solution: The code execution approach presents MCP tools as code APIs instead of direct tool calls. The agent writes code to interact with the server, loading only the tools it needs and processing data in the execution environment — reducing token usage by 98%+.

Capabilities

MCP Server Tool Categories

The OpenAgent Core provides access to open banking financial data through 7 core tool categories.

CategoryToolsPurpose
User Managementcreate_user, get_user, update_user, list_users, search_user_by_emailBasiq user lifecycle
Consentgenerate_consent_url, check_consent_status, explain_consent_flowCDR-compliant bank authorization
Connectionscreate_connection, get_connections, get_connection, sync_connection, get_job_status, search_institutionsBank account linking
Accountsget_accounts, get_account, list_accounts, get_account_summaryBalances and account metadata
Transactionsget_transactions, get_transaction, list_transactions, get_transaction_summaryTransaction history and filtering
Enrichmentenrich_transaction, get_categorization_summary, get_institutionMerchant and category data
Insightsgenerate_insight, get_insights, get_insight, analyze_spending_patterns, get_financial_health_scoreAI-powered financial analysis

Progressive Disclosure Resources

basiq://first-time-setup

6-step onboarding workflow

basiq://consent-flow-guide

CDR consent flow documentation

basiq://tool-prerequisites

Dependency map for tools

basiq://quick-reference

Common workflows & troubleshooting

Prerequisites

Connection Setup

Everything you need before connecting an AI client to the MCP server.

Endpoint

https://your-mcp-server.workers.dev/mcp

Authentication

Authorization: Bearer <TENANT_API_KEY>

Protocol

  • MCP JSON-RPC 2.0
  • initialize • tools/list • tools/call
  • resources/list • resources/read
  • prompts/list • prompts/get
Architecture

Progressive Disclosure

Instead of loading all tool definitions, tools are presented as importable code files — loaded only when needed.

Step 1

Present Tools as Code APIs

Generate a file tree of available tools — the agent explores categories and reads only what it needs.

File Structure
servers/
└── basiq-financial/
    ├── users/
    │   ├── create_user.ts
    │   ├── get_user.ts
    │   ├── update_user.ts
    │   ├── list_users.ts
    │   └── search_user_by_email.ts
    ├── consent/
    │   ├── generate_consent_url.ts
    │   ├── check_consent_status.ts
    │   └── explain_consent_flow.ts
    ├── connections/
    │   ├── create_connection.ts
    │   ├── get_connections.ts
    │   ├── get_connection.ts
    │   ├── sync_connection.ts
    │   ├── get_job_status.ts
    │   └── search_institutions.ts
    ├── accounts/
    │   ├── get_accounts.ts
    │   ├── get_account.ts
    │   ├── list_accounts.ts
    │   └── get_account_summary.ts
    ├── transactions/
    │   ├── get_transactions.ts
    │   ├── get_transaction.ts
    │   ├── list_transactions.ts
    │   └── get_transaction_summary.ts
    ├── enrichment/
    │   ├── enrich_transaction.ts
    │   ├── get_categorization_summary.ts
    │   └── get_institution.ts
    ├── insights/
    │   ├── generate_insight.ts
    │   ├── get_insights.ts
    │   ├── get_insight.ts
    │   ├── analyze_spending_patterns.ts
    │   └── get_financial_health_score.ts
    └── index.ts
Step 2

Tool File Pattern

Each tool corresponds to a typed file that wraps the MCP tools/call method.

servers/basiq-financial/users/create_user.ts
import { callMCPTool } from "../../mcp-client.js";

interface CreateUserInput {
  email?: string;
  mobile?: string;
}

interface CreateUserResponse {
  userId: string;
  message: string;
}

/** Create a Basiq user. First step in the financial data workflow. */
export async function createUser(input: CreateUserInput): Promise<CreateUserResponse> {
  return callMCPTool<CreateUserResponse>("create_user", input);
}
Step 3

MCP Client Implementation

The shared client handles JSON-RPC communication, authentication, and response parsing.

mcp-client.ts
const MCP_URL = process.env.MCP_SERVER_URL || "https://your-mcp-server.workers.dev/mcp";
const TENANT_API_KEY = process.env.TENANT_API_KEY;

export async function callMCPTool<T>(toolName: string, args: Record<string, unknown>): Promise<T> {
  const response = await fetch(MCP_URL, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${TENANT_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: crypto.randomUUID(),
      method: "tools/call",
      params: {
        name: toolName,
        arguments: args,
      },
    }),
  });

  const result = await response.json();
  if (result.error) {
    throw new Error(result.error.message || "MCP tool call failed");
  }
  return result.result?.content?.[0]?.text
    ? JSON.parse(result.result.content[0].text)
    : result.result;
}
Step-by-Step

Instructions for AI Clients

Five steps for efficient tool discovery, data processing, and workflow execution.

1

Discover Tools On-Demand

Do not load all 34+ tool definitions upfront. Instead, explore the directory structure and read only the tools needed for the current task.

List the directory structure — Explore ./servers/basiq-financial/ to find tool categories.

Read only the tools needed — For "create a user and get consent URL", read create_user.ts and generate_consent_url.ts only.

Use search if available — Search for "consent" or "transactions" to load only relevant definitions.

2

Use Resources for Workflow Discovery

Before executing tools, read MCP resources to understand workflows. Resources are small and provide structured guidance — load them instead of inferring from tool descriptions.

// Read first-time setup guide (avoids trial-and-error)
const setupGuide = await readMCPResource(
  "basiq://first-time-setup"
);

// Check tool prerequisites before calling
const prerequisites = await readMCPResource(
  "basiq://tool-prerequisites"
);
3

Filter & Transform Data in Code

Avoid passing large datasets through the model. Process data in the execution environment and return only what's needed — summaries, filtered results, or aggregated values.

// Filter in code, return only what's needed
import * as transactions
  from "./servers/basiq-financial/transactions";

const all = await transactions.getTransactions({
  userId: "usr_abc123",
  from: "2025-01-01",
  to: "2025-01-31"
});

const groceries = all.filter(t =>
  t.category?.toLowerCase().includes("groceries")
);
const total = groceries.reduce(
  (sum, t) => sum + Math.abs(t.amount), 0
);

console.log(`Groceries: $${total.toFixed(2)}`);
console.log(groceries.slice(0, 5)); // Top 5 only
4

Chain Operations Without Context Bloat

Data flows between tools in the execution environment — intermediate results never enter the model's context unless explicitly returned.

import * as users    from "./servers/.../users";
import * as consent  from "./servers/.../consent";
import * as accounts from "./servers/.../accounts";
import * as insights from "./servers/.../insights";

const user = await users.createUser(
  { email: "user@example.com" }
);
const { url } = await consent.generateConsentUrl(
  { userId: user.userId }
);
console.log("Authorize:", url);

// Later — no full account list passed to model
const accts = await accounts.getAccounts(
  { userId: user.userId }
);
const health = await insights.getFinancialHealthScore(
  { userId: user.userId }
);
console.log(`Health score: ${health.score}/100`);
5

Use Control Flow in Code

Loops, conditionals, and retries execute in the code environment — no model round-trips needed for polling or retry logic.

// Poll for consent completion
let complete = false;
while (!complete) {
  const status = await consent.checkConsentStatus(
    { jobId }
  );
  complete =
    status.status === "success" ||
    status.status === "failed";
  if (!complete) {
    await new Promise(
      r => setTimeout(r, 5000) // 5s backoff
    );
  }
}
console.log("Consent flow complete");
Full Example

Complete First-Time User Setup

An end-to-end workflow: create a user, authorize consent, fetch accounts, and generate spending insights.

onboard-and-analyze.ts
import * as users        from "./servers/basiq-financial/users";
import * as consent      from "./servers/basiq-financial/consent";
import * as connections  from "./servers/basiq-financial/connections";
import * as accounts     from "./servers/basiq-financial/accounts";
import * as transactions from "./servers/basiq-financial/transactions";
import * as insights     from "./servers/basiq-financial/insights";

async function onboardUserAndAnalyzeSpending(email: string) {
  // 1. Create user
  const user = await users.createUser({ email });
  console.log(`Created user: ${user.userId}`);

  // 2. Generate consent URL
  const { consentUrl } = await consent.generateConsentUrl({
    userId: user.userId,
    callbackUrl: "https://yourapp.com/callback"
  });
  console.log(`User must authorize: ${consentUrl}`);

  // 3. (User completes consent in browser — out of band)
  // 4. Poll for completion (in production, use webhooks)
  // ... polling logic ...

  // 5. Fetch accounts and transactions
  const accountsList = await accounts.getAccounts({ userId: user.userId });
  const txns = await transactions.getTransactions({
    userId: user.userId,
    from: "2025-01-01",
    to: "2025-01-31"
  });

  // 6. Filter and aggregate in code — don't pass 1000s of rows to model
  const byCategory = txns.reduce((acc, t) => {
    const cat = t.category || "Uncategorized";
    acc[cat] = (acc[cat] || 0) + Math.abs(t.amount);
    return acc;
  }, {} as Record<string, number>);

  // 7. Return summary only
  console.log("Spending by category:", byCategory);

  // 8. Get AI insight (server-side, returns concise summary)
  const insight = await insights.analyzeSpendingPatterns({ userId: user.userId });
  console.log(insight.summary);
}
Security & Persistence

Privacy, Security & Skills

Data isolation, PII handling, and reusable skill patterns for production deployments.

Data Isolation

Intermediate results stay in the execution environment. Data flows between tools without entering the model's context unless explicitly logged or returned.

PII Tokenization

Sensitive data — emails, account numbers — can be tokenized before reaching the model. The MCP client untokenizes when passing to downstream tools.

Deterministic Rules

Define explicit data flow boundaries — e.g. Basiq API → your database, never directly to model context. Data routing is controlled at the execution layer.

State Persistence & Skills

Agents can persist intermediate results and build reusable skills. Add a SKILL.md for structured skill references the model can discover.

skills/save-transactions-csv.ts
import * as transactions
  from "../servers/basiq-financial/transactions";
import fs from "fs";

export async function saveTransactionsAsCsv(
  userId: string,
  from: string,
  to: string
) {
  const txns = await transactions.getTransactions(
    { userId, from, to }
  );
  const csv = txns
    .map(t => [t.date, t.description, t.amount, t.category].join(","))
    .join("\n");
  const path =
    `./workspace/transactions-${userId}-${from}-${to}.csv`;
  await fs.writeFile(path, csv);
  return path;
}
Summary

Best Practices

Key patterns for building efficient, cost-effective AI integrations with the MCP server.

Load Tools On-Demand

Reduces context from ~150K to ~2K tokens by importing only the tools needed for the current task.

Read Resources First

Use basiq://first-time-setup and basiq://tool-prerequisites before executing tool calls.

Filter in Code

Aggregate and filter datasets locally. Avoid passing thousands of rows through model context.

Chain Operations

Data stays in the execution environment between tool calls — no intermediate context bloat.

Control Flow in Code

Polling, retries, and loops execute in code. No model round-trips for operational logic.

Persist State to Files

Save intermediate results to disk. Resume work across sessions and build reusable skills.

References

Further Reading

Reference

Code Execution with MCP

Anthropic's original approach and rationale for the code execution pattern.

Read more
Reference

MCP Protocol for AI Clients

Standard MCP connection details and protocol specification.

Coming soon
Reference

AI Client Integration

Authentication, endpoints, and client configuration guide.

Coming soon
Reference

Quick Start v2

Resources, prompts, and workflows to get started fast.

Coming soon

Document Version 1.0 • Last Updated February 2025 • For OpenAgent Core Documentation