Introduction: The Claude Opportunity
Claude is a capable reasoning engine, but it's also a blank slate. When you ask Claude to approve a loan, price insurance, or issue a permit, it will make up reasonable-sounding answers because it doesn't know your actual rules, thresholds, exceptions, and governance constraints.
That's why enterprises get stuck in "AI POC purgatory"βpilots work in controlled demos, but real production requires that AI agents actually follow your business rules instead of inventing them.
Enter Algorithmation: the discipline of converting your business processes, decisions, and exceptions into machine-readable, versioned, and auditable logic. Combined with Claude's native Model Context Protocol (MCP) support, you can turn your formal processes into executable AI capabilities that remain under governance.
This article shows how.
The Problem: Rules Hidden in Documents and Heads
Most enterprises have critical logic scattered across:
- PDFs and policy documents
- Spreadsheets and condition tables
- Email threads and informal decisions
- Individual subject-matter expert knowledge
When you ask Claude (or any LLM) to help with these processes, Claude can't reliably read or execute what it cannot clearly see. The result: hallucinated decisions, compliance violations, and lost audit trails.
The solution is to surface that institutional knowledge into explicit, machine-readable models before you hand it to an AI agent.
The Solution: UAPF, MCP, and Claude
The Algomation initiative provides three key components:
1. UAPF: The Open Format for Algorithmic Processes
UAPF (Unified Algorithmic Process Format) packages three industry-standard model notations:
- BPMN (Business Process Model and Notation) β defines end-to-end workflows: activities, decisions, human reviews, and escalations
- DMN (Decision Model and Notation) β codifies rules as explicit decision tables: "If credit score β₯ 720 and DTI β€ 35%, then approve; otherwise refer"
- CMMN (Case Management Model and Notation) β models non-linear work like investigations, exceptions, and appeals
These three standards live together in a single .uapf file (a ZIP archive):
loan-approval.uapf
ββ manifest.json
ββ models/
β ββ bpmn/
β β ββ loan-approval-main.bpmn.xml
β ββ dmn/
β β ββ eligibility-rules.dmn.xml
β β ββ risk-grading.dmn.xml
β β ββ offer-configuration.dmn.xml
β ββ cmmn/
β ββ manual-review.cmmn.xml
ββ docs/
ββ README.md
The manifest declares what the package does and what inputs/outputs it expects:
json{
"uapfVersion": "0.1.0",
"id": "io.mybank.loan-approval",
"name": "Retail Loan Approval",
"version": "2.5.0",
"models": {
"bpmn": ["models/bpmn/loan-approval-main.bpmn.xml"],
"dmn": [
"models/dmn/eligibility-rules.dmn.xml",
"models/dmn/risk-grading.dmn.xml",
"models/dmn/offer-configuration.dmn.xml"
],
"cmmn": ["models/cmmn/manual-review.cmmn.xml"]
},
"interfaces": {
"processes": [
{
"id": "LoanApproval",
"bpmnProcessId": "loan_approval_main",
"entryPoint": "StartEvent_ApplicationReceived"
}
],
"decisions": [
{ "id": "EligibilityRules", "dmnDecisionId": "EligibilityDecision" },
{ "id": "RiskGrading", "dmnDecisionId": "RiskGradeDecision" }
]
}
}
Key advantage: Once your process is in UAPF, it becomes portable, versionable, and independent of any vendor's proprietary format.
2. MCP: The Bridge Between Claude and Your Algorithms
The Model Context Protocol is Claude's native way to invoke external tools. Instead of embedding business logic in prompts, you expose your UAPF engine as an MCP server.
An MCP server for loan approval might expose tools like:
typescriptserver.tool(
"uapf_loan_describe_service",
{
description: "Returns metadata about the loan approval UAPF package",
inputSchema: z.object({
packageId: z.string().default("io.mybank.loan-approval")
})
},
// implementation
);
server.tool(
"uapf_loan_run_application",
{
description: "Executes the full loan approval process",
inputSchema: z.object({
application: z.object({
applicantId: z.string(),
name: z.string(),
age: z.number(),
creditScore: z.number(),
monthlyIncome: z.number(),
requestedAmount: z.number()
})
})
},
// implementation
);
server.tool(
"uapf_loan_evaluate_eligibility",
{
description: "Evaluates only the eligibility DMN decision",
inputSchema: z.object({
creditScore: z.number(),
monthlyIncome: z.number(),
monthlyDebt: z.number()
})
},
// implementation
);
When Claude needs to make a loan decision, it:
- Gathers applicant information from the conversation
- Calls uapf_loan_run_application with complete data
- Receives a structured result including decision, limits, rates, and explanations
- Reports back to the user with full transparency
Claude doesn't invent decisionsβit relays the UAPF engine's decision with governance traces.
3. Claude: The Conversational Interface
Claude handles the human side:
- Collecting structured data through natural conversation
- Explaining complex decisions in accessible language
- Asking clarifying questions when data is incomplete
- Documenting decisions for audit
Claude doesn't handle the rule execution sideβthat's the UAPF engine's job.
Practical Example: Algorithmating a Loan Approval Process for Claude
Let's walk through a complete example.
Step 1: Model Your Loan Approval Process
You start with a BPMN workflow that captures the happy path and exceptions:
xml<process id="loan_approval_main" isExecutable="true">
<startEvent id="StartEvent_ApplicationReceived"/>
<task id="Task_CollectData" name="Collect application data"/>
<businessRuleTask id="Task_EligibilityCheck" implementation="dmn:EligibilityDecision"/>
<exclusiveGateway id="Gateway_Eligible" name="Eligible?"/>
<!-- If ineligible, decline immediately -->
<sequenceFlow id="Flow_Decline" sourceRef="Gateway_Eligible" targetRef="EndEvent_Declined">
<conditionExpression>${eligibility == false}</conditionExpression>
</sequenceFlow>
<!-- If eligible, proceed to risk grading -->
<businessRuleTask id="Task_RiskGrading" implementation="dmn:RiskGradeDecision"/>
<businessRuleTask id="Task_OfferConfiguration" implementation="dmn:OfferConfigDecision"/>
<exclusiveGateway id="Gateway_AutoApprove" name="Approve directly?"/>
<!-- High-confidence approvals go straight through -->
<sequenceFlow id="Flow_AutoApprove" sourceRef="Gateway_AutoApprove" targetRef="EndEvent_Approved">
<conditionExpression>${riskScore > 0.8}</conditionExpression>
</sequenceFlow>
<!-- Edge cases go to manual review -->
<callActivity id="CallManualReview" calledElement="ManualReviewCase"/>
<endEvent id="EndEvent_Approved"/>
<endEvent id="EndEvent_Declined"/>
</process>
Next, you codify your eligibility rules as a DMN decision table:
xml<decision id="EligibilityDecision">
<decisionTable hitPolicy="UNIQUE">
<input id="inAge">
<inputExpression typeRef="number">applicant.age</inputExpression>
</input>
<input id="inCreditScore">
<inputExpression typeRef="number">applicant.creditScore</inputExpression>
</input>
<input id="inEmploymentStatus">
<inputExpression typeRef="string">applicant.employmentStatus</inputExpression>
</input>
<output id="outEligible" name="eligibility" typeRef="boolean"/>
<!-- Rule 1: Standard eligibility -->
<rule>
<inputEntry>[21..70]</inputEntry>
<inputEntry>[620..]</inputEntry>
<inputEntry>"EMPLOYED","SELF_EMPLOYED"</inputEntry>
<outputEntry>true</outputEntry>
</rule>
<!-- Rule 2: Anything else is ineligible -->
<rule>
<inputEntry>otherwise</inputEntry>
<inputEntry>otherwise</inputEntry>
<inputEntry>otherwise</inputEntry>
<outputEntry>false</outputEntry>
</rule>
</decisionTable>
</decision>
Step 2: Deploy the UAPF Engine
You host a small REST API that loads your UAPF package and executes it:
typescript// In your Node.js service
import { UapfEngine } from '@algomation/engine';
import express from 'express';
const engine = new UapfEngine();
await engine.loadPackage('loan-approval.uapf');
const app = express();
app.post('/uapf/loan/execute-process', async (req, res) => {
const { application } = req.body;
const result = await engine.executeProcess(
'loan_approval_main',
application
);
// Result includes status, limits, rates, and decision explanations
res.json({
applicationId: application.applicantId,
status: result.decision, // "approved", "declined", or "manual_review"
creditLimit: result.creditLimit,
interestRate: result.interestRate,
explanations: result.decisionTraces, // Why each decision was made
packageVersion: "2.5.0"
});
});
app.post('/uapf/loan/evaluate-eligibility', async (req, res) => {
const { applicant } = req.body;
const eligible = await engine.evaluateDecision(
'EligibilityDecision',
applicant
);
res.json({ eligible, reasons: eligible.explanations });
});
app.listen(3000);
Step 3: Wrap the Engine as an MCP Server
Create a small MCP server that adapts the HTTP API into Claude-callable tools:
typescript// mcp/uapf-loan-approval/src/server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import axios from "axios";
const server = new McpServer({
name: "uapf-loan-approval",
version: "1.0.0"
});
const ENGINE_BASE = process.env.UAPF_ENGINE_BASE ?? "http://localhost:3000/uapf/loan";
// Tool 1: Service metadata
server.tool(
"uapf_loan_describe_service",
{
description: "Returns metadata about the loan approval service",
inputSchema: z.object({})
},
async () => ({
packageId: "io.mybank.loan-approval",
name: "Retail Loan Approval",
version: "2.5.0",
supportedProcesses: ["LoanApproval"],
supportedDecisions: ["EligibilityRules", "RiskGrading", "OfferConfiguration"],
minimumCreditScore: 620,
minimumAge: 21,
maximumAge: 70
})
);
// Tool 2: Run full approval process
server.tool(
"uapf_loan_run_application",
{
description: "Executes the complete loan approval process for an applicant",
inputSchema: z.object({
application: z.object({
applicantId: z.string(),
name: z.string(),
age: z.number().int(),
creditScore: z.number().int(),
monthlyIncome: z.number(),
monthlyDebt: z.number(),
requestedAmount: z.number(),
employmentStatus: z.enum(["EMPLOYED", "SELF_EMPLOYED", "RETIRED", "STUDENT"])
})
})
},
async ({ input }) => {
const response = await axios.post(`${ENGINE_BASE}/execute-process`, input);
return response.data;
}
);
// Tool 3: Evaluate eligibility only
server.tool(
"uapf_loan_evaluate_eligibility",
{
description: "Quick check: is this applicant eligible?",
inputSchema: z.object({
creditScore: z.number().int(),
age: z.number().int(),
employmentStatus: z.enum(["EMPLOYED", "SELF_EMPLOYED", "RETIRED", "STUDENT"])
})
},
async ({ input }) => {
const response = await axios.post(
`${ENGINE_BASE}/evaluate-eligibility`,
{ applicant: input }
);
return response.data;
}
);
const transport = new StdioServerTransport();
transport.connect(server);
Step 4: Configure Claude with the MCP Server
In Claude Desktop or your agent host, register the MCP server:
json// ~/.claude/mcp.json
{
"mcpServers": {
"uapf-loan-approval": {
"command": "node",
"args": ["mcp/uapf-loan-approval/build/server.js"]
}
}
}
Restart Claude Desktop. The MCP server starts, and Claude now has access to the loan approval tools.
Step 5: Give Claude Clear Instructions
Add a system prompt that tells Claude how to use these tools:
```
You are a Loan Approval Assistant for MyBank.
Your job is to help customers explore loan options and understand their approval status.
You have access to the official loan approval algorithm via MCP tools.
These tools are the single source of truth for approval decisions.
Available tools:
- uapf_loan_describe_service: Get info about the loan approval service
- uapf_loan_run_application: Execute the full approval process
- uapf_loan_evaluate_eligibility: Quick eligibility check
When a customer asks about a loan:
1. Collect the required information through conversation:
- Full name, age
- Current employment status
- Monthly income and debt obligations
- Desired loan amount
2. Once you have all required fields, call uapf_loan_run_application
with the applicant's data.
3. Report the decision exactly as returned by the tool:
- Status (approved/declined/manual review)
- Credit limit and interest rate
- Key reasons for the decision
4. Always include this line:
"This decision was made using our algorithmated loan approval process
(UAPF package io.mybank.loan-approval v2.5.0)."
5. Do NOT:
- Modify the decision returned by the tool
- Invent interest rates or limits
- Override policy thresholds
- Make promises about manual review outcomes
If a customer's application is marked for manual review, explain that
a loan officer will contact them within 1 business day.
If they ask about your reasoning, cite the decision explanations
returned by the tool, not your own judgment.
```
Step 6: Claude in Action
A conversation flow:
Customer: "I'd like to apply for a $10,000 loan." Claude: "I'd be happy to help! To process your application, I'll need a few pieces of information. Let me gather those from you: Your full name? Your age? What's your employment status? What's your approximate monthly income? Do you have any existing monthly debt (car payment, credit card, etc.)?" Customer: "I'm Jane Doe, 35 years old. I'm employed as a software engineer. My monthly income is $6,500, and my debt is about $800." Claude: [Calls uapf_loan_run_application with the data] [MCP server β REST API β UAPF Engine β returns result] Claude: "Great news, Jane! Based on our algorithmated approval process, your application is approved. Here's what we can offer: Credit Limit: $8,500 Interest Rate: 8.2% APR Monthly Payment (24 months): $380 Why this decision: Your credit score of 740 is in the low-risk band Your debt-to-income ratio (12%) is well below our 35% threshold Your employment history meets our stability requirements This decision was made using our algorithmated loan approval process (UAPF package io.mybank.loan-approval v2.5.0). Your funds will be available in your account within 2 business days. Is there anything else you'd like to know?" Key Benefits of This Approach
1. Governance and Auditability
Every decision is traceable to a specific BPMN process version, DMN rule, and execution timestamp. Regulators see not a black box, but an explicit policy.
2. Speed Without Risk
Approval decisions that meet clear criteria run instantly, while edge cases still route to human review. You get the efficiency of automation without sacrificing judgment.
3. Consistency Across Channels
The same UAPF package powers your API, mobile app, call center, and Claude agent. One algorithm, multiple interfaces.
4. Maintenance and Versioning
Update your DMN rules, test them in Algomation Studio, version the package, and deploy the new UAPF to production. All agents automatically use the updated logic.
5. Separates Concerns
- Claude handles conversation and data collection
- UAPF engine handles rule execution and governance
- MCP is the clean boundary between them
6. Reusability
Once you have a UAPF package, you can expose it to any MCP-capable agent (Claude, Grok, custom orchestrators) without changing the package.
How This Scales to Complex Processes
The examples above show straightforward approval/decline flows. Real-world processes are messier:
- Tiered reviews: "If risk score between 0.5 and 0.8, send to manager; if < 0.5, escalate to director"
- Conditional workflows: "If applicant has collateral, skip income verification"
- Exception handling: "If applicant has recent bankruptcy, always manual review"
- Parallel approvals: "Compliance and risk review in parallel, both must approve"
BPMN, DMN, and CMMN handle all of these. Your UAPF package can encode arbitrarily complex logic, and Claude simply calls the tools and relays the results.
Limitations and Considerations
What UAPF + MCP Is NOT
- Not a replacement for human judgment β manual review cases still need humans
- Not a way to automate away accountability β governance traces mean your organization remains responsible
- Not set-and-forget β you must maintain DMN rules as policies change, test scenarios, and version packages
Technical Considerations
- UAPF engine hosting β you run the engine on-prem or in your VPC, not in Claude (Claude only calls tools)
- Latency β REST calls to the engine add a few hundred milliseconds; appropriate for loan decisions, maybe not for real-time fraud scoring
- Uptime β the UAPF engine becomes a critical dependency; version, monitor, and test it accordingly
Organizational Challenges
- Process discovery β surfacing all your implicit rules takes discipline
- Cross-functional alignment β risk, compliance, operations, and legal must agree on the formal model
- Tool adoption β teams used to informal spreadsheets may resist formality initially
Getting Started
- Pick a High-Value Process
Start with something high-impact but not mission-critical: loan pre-qualification, permit eligibility check, insurance quote, onboarding eligibility, etc. - Model It in BPMN/DMN/CMMN
Use Algomation Studio or open-source tools like Signavio or Camunda Modeler to capture your process, decisions, and cases. - Package as UAPF
Export your models as a UAPF package (or create the manifest manually). - Build a REST Wrapper
Write a small service that loads the UAPF package and exposes /execute-process and /evaluate-decision endpoints. TypeScript + Express is fine for prototypes. - Create an MCP Server
Wrap the REST API as an MCP server. Use the @modelcontextprotocol/sdk npm package and follow the pattern shown above. - Test with Claude
Register the MCP server in Claude Desktop, give Claude the system prompt, and test a few scenarios. - Iterate
Update the DMN rules, test new scenarios in Algomation Studio, version the UAPF package, and re-deploy.
Conclusion
The combination of Algorithmation (UAPF), MCP, and Claude creates a powerful pattern for enterprise AI:
- Algorithms stay explicit β rules live in BPMN/DMN/CMMN, not LLM weights
- Governance stays intact β decisions are auditable and traceable
- Claude becomes productive β it handles conversation; the algorithm handles logic
- Processes scale β one UAPF package, multiple agents and interfaces
This is not "AI magic." It's disciplined, explainable, governed intelligenceβexactly what enterprises need.
If you have complex processes that require consistency, auditability, and compliance, Algorithmation via UAPF + MCP + Claude is a mature, production-ready approach.
```